added user notification preferences
This commit is contained in:
parent
0ceadf2ab1
commit
d772365b23
|
@ -39,6 +39,7 @@ import { GuidedTourModule } from './library/guided-tour/guided-tour.module';
|
||||||
import { Oauth2DialogModule } from './ui/misc/oauth2-dialog/oauth2-dialog.module';
|
import { Oauth2DialogModule } from './ui/misc/oauth2-dialog/oauth2-dialog.module';
|
||||||
import { OpenDMPCustomTranslationCompiler } from './utilities/translate/opendmp-custom-translation-compiler';
|
import { OpenDMPCustomTranslationCompiler } from './utilities/translate/opendmp-custom-translation-compiler';
|
||||||
import { CoreAnnotationServiceModule } from 'annotation-service/services/core-service.module';
|
import { CoreAnnotationServiceModule } from 'annotation-service/services/core-service.module';
|
||||||
|
import { CoreNotificationServiceModule } from '@notification-service/services/core-service.module';
|
||||||
|
|
||||||
// AoT requires an exported function for factories
|
// AoT requires an exported function for factories
|
||||||
export function HttpLoaderFactory(languageHttpService: LanguageHttpService) {
|
export function HttpLoaderFactory(languageHttpService: LanguageHttpService) {
|
||||||
|
|
|
@ -5,6 +5,7 @@ $mat-card-header-size: 40px !default;
|
||||||
width: $mat-card-header-size;
|
width: $mat-card-header-size;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-bar {
|
.progress-bar {
|
||||||
|
|
|
@ -208,6 +208,26 @@
|
||||||
<div class="row d-flex mb-5">
|
<div class="row d-flex mb-5">
|
||||||
<div class="col-auto ml-auto"><button mat-raised-button class="save-btn" type="button" (click)="save()">{{'USER-PROFILE.ACTIONS.SAVE' | translate}}</button></div>
|
<div class="col-auto ml-auto"><button mat-raised-button class="save-btn" type="button" (click)="save()">{{'USER-PROFILE.ACTIONS.SAVE' | translate}}</button></div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mb-5">
|
||||||
|
<div class="col-12">
|
||||||
|
<mat-accordion class="w-100">
|
||||||
|
<mat-expansion-panel (opened)="expandPreferences()">
|
||||||
|
<mat-expansion-panel-header>
|
||||||
|
<mat-panel-title>
|
||||||
|
<span>{{ 'NOTIFICATION-SERVICE.USER-PROFILE.TITLE' | translate}}</span>
|
||||||
|
</mat-panel-title>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<ng-container *ngIf="expandedPreferences">
|
||||||
|
<app-user-profile-notifier-list-editor></app-user-profile-notifier-list-editor>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-expansion-panel>
|
||||||
|
</mat-accordion>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
|
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
|
||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { FormBuilder, UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
import { UntypedFormArray, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { ActivatedRoute, Params, Router } from '@angular/router';
|
import { ActivatedRoute, Params, Router } from '@angular/router';
|
||||||
import { RoleOrganizationType } from '@app/core/common/enum/role-organization-type';
|
import { RoleOrganizationType } from '@app/core/common/enum/role-organization-type';
|
||||||
|
@ -56,6 +56,7 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes
|
||||||
nestedCount = [];
|
nestedCount = [];
|
||||||
nestedIndex = 0;
|
nestedIndex = 0;
|
||||||
tenants: Observable<Array<string>>;
|
tenants: Observable<Array<string>>;
|
||||||
|
expandedPreferences: boolean = false;
|
||||||
|
|
||||||
organisationsAutoCompleteConfiguration: MultipleAutoCompleteConfiguration = {
|
organisationsAutoCompleteConfiguration: MultipleAutoCompleteConfiguration = {
|
||||||
filterFn: this.filterOrganisations.bind(this),
|
filterFn: this.filterOrganisations.bind(this),
|
||||||
|
@ -447,4 +448,9 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes
|
||||||
const returnUrl = '/profile';
|
const returnUrl = '/profile';
|
||||||
this.authService.prepareAuthRequest(from(this.keycloakService.getToken()), {}).pipe(takeUntil(this._destroyed)).subscribe(() => this.authService.onAuthenticateSuccess(returnUrl), (error) => this.authService.onAuthenticateError(error));
|
this.authService.prepareAuthRequest(from(this.keycloakService.getToken()), {}).pipe(takeUntil(this._destroyed)).subscribe(() => this.authService.onAuthenticateSuccess(returnUrl), (error) => this.authService.onAuthenticateError(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Preferences
|
||||||
|
expandPreferences(): void {
|
||||||
|
this.expandedPreferences = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { AddAccountDialogComponent } from './add-account/add-account-dialog.comp
|
||||||
import { AddAccountDialogModule } from './add-account/add-account-dialog.module';
|
import { AddAccountDialogModule } from './add-account/add-account-dialog.module';
|
||||||
import { UserProfileComponent } from './user-profile.component';
|
import { UserProfileComponent } from './user-profile.component';
|
||||||
import { UserProfileRoutingModule } from './user-profile.routing';
|
import { UserProfileRoutingModule } from './user-profile.routing';
|
||||||
|
import { UserProfileNotifierListModule } from '@notification-service/ui/user-profile/notifier-list/user-profile-notifier-list-editor.module';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -19,7 +20,8 @@ import { UserProfileRoutingModule } from './user-profile.routing';
|
||||||
UserProfileRoutingModule,
|
UserProfileRoutingModule,
|
||||||
AutoCompleteModule,
|
AutoCompleteModule,
|
||||||
AddAccountDialogModule,
|
AddAccountDialogModule,
|
||||||
FormValidationErrorsDialogModule
|
FormValidationErrorsDialogModule,
|
||||||
|
UserProfileNotifierListModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
UserProfileComponent
|
UserProfileComponent
|
||||||
|
|
|
@ -1119,6 +1119,39 @@
|
||||||
"ACTIONS": {
|
"ACTIONS": {
|
||||||
"DELETE": "Delete"
|
"DELETE": "Delete"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"TYPES": {
|
||||||
|
"CONTACT-TYPE": {
|
||||||
|
"EMAIL": "Email",
|
||||||
|
"IN-APP": "In App"
|
||||||
|
},
|
||||||
|
"IS-ACTIVE": {
|
||||||
|
"ACTIVE": "Active",
|
||||||
|
"INACTIVE": "Inactive"
|
||||||
|
},
|
||||||
|
"NOTIFICATION-TYPE": {
|
||||||
|
"REGISTRATION-INVITATION": "Registration Invitation",
|
||||||
|
"TOTP-OVERRIDE-USED": "TOPT Override Used",
|
||||||
|
"CREDENTIAL-RESET": "Credential Reset",
|
||||||
|
"DIRECT-LINK": "Direct Link",
|
||||||
|
"FORGET-ME-REQUEST": "Forget me Request",
|
||||||
|
"WHAT-YOU-KNOW-ABOUT-ME-REQUEST": "'What you Know about me' request",
|
||||||
|
"WHAT-YOU-KNOW-ABOUT-ME-REQUEST-COMPLETED": "Completion of 'what you Know about me' request",
|
||||||
|
"EMAIL-RESET-REQUEST": "Email reset request",
|
||||||
|
"EMAIL-RESET-AWARENESS": "Awareness of 'email reset' request",
|
||||||
|
"EMAIL-RESET-REMOVE": "Remove email reset request"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"USER-PROFILE": {
|
||||||
|
"TITLE": "Notification Preferences",
|
||||||
|
"NOTIFIER-LIST-EDITOR": {
|
||||||
|
"ACTIONS": {
|
||||||
|
"SAVE": "Save"
|
||||||
|
},
|
||||||
|
"MESSAGES": {
|
||||||
|
"ERROR": "Something went wrong while trying to load your notification preferences."
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"DESCRIPTION-TEMPLATE-TYPE-EDITOR": {
|
"DESCRIPTION-TEMPLATE-TYPE-EDITOR": {
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
export enum ContactInfoType {
|
||||||
|
Email = 0,
|
||||||
|
MobilePhone = 1,
|
||||||
|
LandLinePhone = 2,
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
export enum ContactType {
|
||||||
|
Email = 0,
|
||||||
|
SlackBroadcast = 1,
|
||||||
|
Sms = 2,
|
||||||
|
InApp = 3,
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
export enum IsActive {
|
||||||
|
Inactive = 0,
|
||||||
|
Active = 1
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
export enum NotificationInAppTracking {
|
||||||
|
Stored = 0,
|
||||||
|
Delivered = 1
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
export enum NotificationNotifyState {
|
||||||
|
Pending = 0,
|
||||||
|
Processing = 1,
|
||||||
|
Successful = 2,
|
||||||
|
Error = 3,
|
||||||
|
Omitted = 4
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
export enum NotificationTemplateChannel {
|
||||||
|
Email = 0,
|
||||||
|
SlackBroadcast = 1,
|
||||||
|
Sms = 2,
|
||||||
|
InApp = 3,
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
export enum NotificationTemplateKind {
|
||||||
|
Draft = 0,
|
||||||
|
Secondary = 1,
|
||||||
|
Primary = 2,
|
||||||
|
Default = 3
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
export enum NotificationTrackingProcess {
|
||||||
|
Pending = 0,
|
||||||
|
Processing = 1,
|
||||||
|
Completed = 2,
|
||||||
|
Error = 3,
|
||||||
|
Omitted = 4
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
export enum NotificationTrackingState {
|
||||||
|
/// <summary>
|
||||||
|
/// Initial state
|
||||||
|
/// </summary>
|
||||||
|
Undefined = 0,
|
||||||
|
/// <summary>
|
||||||
|
/// Final for notifiers that do not provide any kind of tracking
|
||||||
|
/// </summary>
|
||||||
|
NA = 1,
|
||||||
|
Queued = 2,
|
||||||
|
Sent = 3,
|
||||||
|
Delivered = 4,
|
||||||
|
Undelivered = 5,
|
||||||
|
Failed = 6,
|
||||||
|
Unsent = 7
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
export enum NotificationType {
|
||||||
|
RegistrationInvitation = '4fdbfa80-7a71-4a69-b854-67cbb70648f1',
|
||||||
|
TotpOverrideUsed = '065deecd-21bb-44af-9983-e660fdf24bc4',
|
||||||
|
CredentialReset = '90db0b46-42de-bd89-aebf-6f27efeb256e',
|
||||||
|
DirectLink = 'bfe68845-cb05-4c5a-a03d-29161a7c9660',
|
||||||
|
ForgetMeRequest = '4542262a-22f8-4baa-9db6-1c8e70ac1dbb',
|
||||||
|
WhatYouKnowAboutMeRequest = 'd3cd55fe-8da2-42e7-a501-3795ee4f16d3',
|
||||||
|
WhatYouKnowAboutMeRequestCompleted = '55736f7a-83ab-4190-af43-9d031a6f9612',
|
||||||
|
EmailResetRequest = '223bb607-efa1-4ce7-99ec-4beabfef9a8b',
|
||||||
|
EmailResetAwareness = 'c9bc3f16-057e-4bba-8a5f-36bd835e5604',
|
||||||
|
EmailResetRemove = '1aeb49e8-c817-4088-8b45-08e0a5155796',
|
||||||
|
Unknown1 = "5b1d6c52-88f9-418b-9b8a-6f1f963d9ead",
|
||||||
|
Unknown2 = "b542b606-acc6-4629-adef-4d8ee2f01222",
|
||||||
|
Unknown3 = "33790bad-94d4-488a-8ee2-7f6295ca18ea",
|
||||||
|
Unknown4 = "4904dea2-5079-46d3-83be-3a19c9ab45dc",
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
export enum NotificationServicePermission {
|
||||||
|
//Tenant
|
||||||
|
BrowseTenant = 'BrowseTenant',
|
||||||
|
EditTenant = 'EditTenant',
|
||||||
|
DeleteTenant = 'DeleteTenant',
|
||||||
|
//Tenant Configuration
|
||||||
|
BrowseTenantConfiguration = 'BrowseTenantConfiguration',
|
||||||
|
BrowseTenantConfigurationSlackBroadcast = 'BrowseTenantConfigurationSlackBroadcast',
|
||||||
|
BrowseTenantConfigurationSmsClient = 'BrowseTenantConfigurationSmsClient',
|
||||||
|
BrowseTenantConfigurationEmailClient = 'BrowseTenantConfigurationEmailClient',
|
||||||
|
BrowseTenantConfigurationUserLocale = 'BrowseTenantConfigurationUserLocale',
|
||||||
|
BrowseTenantAvailableNotifierList = 'BrowseTenantAvailableNotifierList',
|
||||||
|
BrowseTenantConfigurationNotifierList = 'BrowseTenantConfigurationNotifierList',
|
||||||
|
DeleteTenantConfiguration = 'DeleteTenantConfiguration',
|
||||||
|
EditTenantConfiguration = 'EditTenantConfiguration',
|
||||||
|
//User
|
||||||
|
BrowseUser = 'BrowseUser',
|
||||||
|
EditUser = 'EditUser',
|
||||||
|
DeleteUser = 'DeleteUser',
|
||||||
|
//User Notification Preference
|
||||||
|
BrowseUserNotificationPreference = 'BrowseUserNotificationPreference',
|
||||||
|
EditUserNotificationPreference = 'EditUserNotificationPreference',
|
||||||
|
DeleteUserNotificationPreference = 'DeleteUserNotificationPreference',
|
||||||
|
//Contact Info
|
||||||
|
BrowseContactInfo = 'BrowseContactInfo',
|
||||||
|
//Profile
|
||||||
|
BrowseUserProfile = 'BrowseUserProfile',
|
||||||
|
//Notifications
|
||||||
|
SubmitNotification = 'SubmitNotification',
|
||||||
|
BrowseNotification = 'BrowseNotification',
|
||||||
|
BrowseNotificationSensitive = 'BrowseNotificationSensitive',
|
||||||
|
DeleteNotification = 'DeleteNotification',
|
||||||
|
//Notification Templates
|
||||||
|
BrowseNotificationTemplate = 'BrowseNotificationTemplate',
|
||||||
|
SubmitNotificationTemplate = 'SubmitNotificationTemplate',
|
||||||
|
EditNotificationTemplate = 'EditNotificationTemplate',
|
||||||
|
DeleteNotificationTemplate = 'DeleteNotificationTemplate',
|
||||||
|
//ForgetMe
|
||||||
|
BrowseForgetMe = 'BrowseForgetMe',
|
||||||
|
EditForgetMe = 'EditForgetMe',
|
||||||
|
DeleteForgetMe = 'DeleteForgetMe',
|
||||||
|
//WhatYouKnowAboutMe
|
||||||
|
BrowseWhatYouKnowAboutMe = 'BrowseWhatYouKnowAboutMe',
|
||||||
|
EditWhatYouKnowAboutMe = 'EditWhatYouKnowAboutMe',
|
||||||
|
DeleteWhatYouKnowAboutMe = 'DeleteWhatYouKnowAboutMe',
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
export enum TenantConfigurationType {
|
||||||
|
SlackBroadcast = 0,
|
||||||
|
EmailClientConfiguration = 1,
|
||||||
|
SmsClientConfiguration = 2,
|
||||||
|
DefaultUserLocale = 3,
|
||||||
|
NotifierList = 4
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { BaseEnumUtilsService } from '@common/base/base-enum-utils.service';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { ContactType } from '@notification-service/core/enum/contact-type.enum';
|
||||||
|
import { IsActive } from '@notification-service/core/enum/is-active.enum';
|
||||||
|
import { NotificationInAppTracking } from '@notification-service/core/enum/notification-inapp-tracking.enum';
|
||||||
|
import { NotificationNotifyState } from '@notification-service/core/enum/notification-notify-state.enum';
|
||||||
|
import { NotificationTemplateChannel } from '@notification-service/core/enum/notification-template-channel.enum';
|
||||||
|
import { NotificationTemplateKind } from '@notification-service/core/enum/notification-template-kind.enum';
|
||||||
|
import { NotificationTrackingProcess } from '@notification-service/core/enum/notification-tracking-process.enum';
|
||||||
|
import { NotificationTrackingState } from '@notification-service/core/enum/notification-tracking-state.enum';
|
||||||
|
import { NotificationType } from '@notification-service/core/enum/notification-type.enum';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NotificationServiceEnumUtils extends BaseEnumUtilsService {
|
||||||
|
constructor(private language: TranslateService) { super(); }
|
||||||
|
|
||||||
|
|
||||||
|
public toIsActiveString(value: IsActive): string {
|
||||||
|
switch (value) {
|
||||||
|
case IsActive.Active: return this.language.instant('NOTIFICATION-SERVICE.TYPES.IS-ACTIVE.ACTIVE');
|
||||||
|
case IsActive.Inactive: return this.language.instant('NOTIFICATION-SERVICE.TYPES.IS-ACTIVE.INACTIVE');
|
||||||
|
default: return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public toNotificationTypeString(value: NotificationType): string {
|
||||||
|
switch (value) {
|
||||||
|
case NotificationType.RegistrationInvitation: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TYPE.REGISTRATION-INVITATION');
|
||||||
|
case NotificationType.TotpOverrideUsed: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TYPE.TOTP-OVERRIDE-USED');
|
||||||
|
case NotificationType.CredentialReset: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TYPE.CREDENTIAL-RESET');
|
||||||
|
case NotificationType.DirectLink: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TYPE.DIRECT-LINK');
|
||||||
|
case NotificationType.ForgetMeRequest: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TYPE.FORGET-ME-REQUEST');
|
||||||
|
case NotificationType.WhatYouKnowAboutMeRequest: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TYPE.WHAT-YOU-KNOW-ABOUT-ME-REQUEST');
|
||||||
|
case NotificationType.WhatYouKnowAboutMeRequestCompleted: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TYPE.WHAT-YOU-KNOW-ABOUT-ME-REQUEST-COMPLETED');
|
||||||
|
case NotificationType.EmailResetRequest: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TYPE.EMAIL-RESET-REQUEST');
|
||||||
|
case NotificationType.EmailResetAwareness: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TYPE.EMAIL-RESET-AWARENESS');
|
||||||
|
case NotificationType.EmailResetRemove: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TYPE.EMAIL-RESET-REMOVE');
|
||||||
|
case NotificationType.Unknown1: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TYPE.UNKOWN1');
|
||||||
|
case NotificationType.Unknown2: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TYPE.UNKOWN2');
|
||||||
|
case NotificationType.Unknown3: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TYPE.UNKOWN3');
|
||||||
|
case NotificationType.Unknown4: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TYPE.UNKOWN4');
|
||||||
|
default: return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public toContactTypeString(value: ContactType): string {
|
||||||
|
switch (value) {
|
||||||
|
case ContactType.Email: return this.language.instant('NOTIFICATION-SERVICE.TYPES.CONTACT-TYPE.EMAIL');
|
||||||
|
case ContactType.SlackBroadcast: return this.language.instant('NOTIFICATION-SERVICE.TYPES.CONTACT-TYPE.SLACK-BROADCAST');
|
||||||
|
case ContactType.Sms: return this.language.instant('NOTIFICATION-SERVICE.TYPES.CONTACT-TYPE.SMS');
|
||||||
|
case ContactType.InApp: return this.language.instant('NOTIFICATION-SERVICE.TYPES.CONTACT-TYPE.IN-APP');
|
||||||
|
default: return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public toNotificationNotifyStateString(value: NotificationNotifyState): string {
|
||||||
|
switch (value) {
|
||||||
|
case NotificationNotifyState.Pending: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-NOTIFY-STATE.PENDING');
|
||||||
|
case NotificationNotifyState.Processing: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-NOTIFY-STATE.PROCESSING');
|
||||||
|
case NotificationNotifyState.Successful: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-NOTIFY-STATE.SUCCESSFUL');
|
||||||
|
case NotificationNotifyState.Error: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-NOTIFY-STATE.ERROR');
|
||||||
|
case NotificationNotifyState.Omitted: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-NOTIFY-STATE.OMITTED');
|
||||||
|
default: return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public toNotificationTrackingStateString(value: NotificationTrackingState): string {
|
||||||
|
switch (value) {
|
||||||
|
case NotificationTrackingState.Undefined: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TRACKING-STATE.UNDEFINED');
|
||||||
|
case NotificationTrackingState.NA: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TRACKING-STATE.NA');
|
||||||
|
case NotificationTrackingState.Queued: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TRACKING-STATE.QUEUED');
|
||||||
|
case NotificationTrackingState.Sent: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TRACKING-STATE.SENT');
|
||||||
|
case NotificationTrackingState.Delivered: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TRACKING-STATE.DELIVERED');
|
||||||
|
case NotificationTrackingState.Undelivered: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TRACKING-STATE.UNDELIVERED');
|
||||||
|
case NotificationTrackingState.Failed: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TRACKING-STATE.FAILED');
|
||||||
|
case NotificationTrackingState.Unsent: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TRACKING-STATE.UNSENT');
|
||||||
|
default: return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public toNotificationTrackingProcessString(value: NotificationTrackingProcess): string {
|
||||||
|
switch (value) {
|
||||||
|
case NotificationTrackingProcess.Pending: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TRACKING-PROCESS.PENDING');
|
||||||
|
case NotificationTrackingProcess.Processing: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TRACKING-PROCESS.PROCESSING');
|
||||||
|
case NotificationTrackingProcess.Completed: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TRACKING-PROCESS.COMPLETED');
|
||||||
|
case NotificationTrackingProcess.Error: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TRACKING-PROCESS.ERROR');
|
||||||
|
case NotificationTrackingProcess.Omitted: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TRACKING-PROCESS.OMITTED');
|
||||||
|
default: return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public toNotificationInAppTrackingString(value: NotificationInAppTracking): string {
|
||||||
|
switch (value) {
|
||||||
|
case NotificationInAppTracking.Delivered: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-INAPP-TRACKING.DELIVERED');
|
||||||
|
case NotificationInAppTracking.Stored: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-INAPP-TRACKING.STORED');
|
||||||
|
default: return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public toNotificationChannelString(value: NotificationTemplateChannel): string {
|
||||||
|
switch (value) {
|
||||||
|
case NotificationTemplateChannel.Email: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TEMPLATE-CHANNEL.EMAIL');
|
||||||
|
case NotificationTemplateChannel.SlackBroadcast: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TEMPLATE-CHANNEL.SLACK-BROADCAST');
|
||||||
|
case NotificationTemplateChannel.Sms: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TEMPLATE-CHANNEL.SMS');
|
||||||
|
case NotificationTemplateChannel.InApp: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TEMPLATE-CHANNEL.IN-APP');
|
||||||
|
default: return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public toNotificationTemplateKindString(value: NotificationTemplateKind): string {
|
||||||
|
switch (value) {
|
||||||
|
case NotificationTemplateKind.Default: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TEMPLATE-KIND.DEFAULT');
|
||||||
|
case NotificationTemplateKind.Primary: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TEMPLATE-KIND.PRIMARY');
|
||||||
|
case NotificationTemplateKind.Secondary: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TEMPLATE-KIND.SECONDARY');
|
||||||
|
case NotificationTemplateKind.Draft: return this.language.instant('NOTIFICATION-SERVICE.TYPES.NOTIFICATION-TEMPLATE-KIND.DRAFT');
|
||||||
|
default: return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { DatePipe } from '@angular/common';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonFormattingModule } from '@common/formatting/common-formatting.module';
|
||||||
|
import { PipeService } from '@common/formatting/pipe.service';
|
||||||
|
import { IsActiveTypePipe } from '@notification-service/core/formatting/pipes/is-active-type.pipe';
|
||||||
|
import { NotificationInAppTrackingTypePipe } from '@notification-service/core/formatting/pipes/notification-inapp-tracking-type.pipe';
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// This is shared module that provides all notification service formatting utils. Its imported only once.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonFormattingModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
IsActiveTypePipe,
|
||||||
|
NotificationInAppTrackingTypePipe
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
CommonFormattingModule,
|
||||||
|
IsActiveTypePipe,
|
||||||
|
NotificationInAppTrackingTypePipe
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
PipeService,
|
||||||
|
DatePipe,
|
||||||
|
IsActiveTypePipe,
|
||||||
|
NotificationInAppTrackingTypePipe
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class NotificationServiceFormattingModule { }
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { Pipe, PipeTransform } from '@angular/core';
|
||||||
|
import { NotificationServiceEnumUtils } from '@notification-service/core/formatting/enum-utils.service';
|
||||||
|
|
||||||
|
@Pipe({ name: 'IsActiveTypeFormat' })
|
||||||
|
export class IsActiveTypePipe implements PipeTransform {
|
||||||
|
constructor(private enumUtils: NotificationServiceEnumUtils) { }
|
||||||
|
|
||||||
|
public transform(value): any {
|
||||||
|
return this.enumUtils.toIsActiveString(value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { Pipe, PipeTransform } from '@angular/core';
|
||||||
|
import { NotificationServiceEnumUtils } from '@notification-service/core/formatting/enum-utils.service';
|
||||||
|
|
||||||
|
@Pipe({ name: 'NotificationInAppTrackingTypeFormat' })
|
||||||
|
export class NotificationInAppTrackingTypePipe implements PipeTransform {
|
||||||
|
constructor(private enumUtils: NotificationServiceEnumUtils) { }
|
||||||
|
|
||||||
|
public transform(value): any {
|
||||||
|
return this.enumUtils.toNotificationInAppTrackingString(value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { Guid } from '@common/types/guid';
|
||||||
|
import { IsActive } from '@notification-service/core/enum/is-active.enum';
|
||||||
|
import { NotificationInAppTracking } from '@notification-service/core/enum/notification-inapp-tracking.enum';
|
||||||
|
import { NotificationServiceUser } from '@notification-service/core/model/user.model';
|
||||||
|
|
||||||
|
export interface InAppNotification {
|
||||||
|
id: Guid;
|
||||||
|
user: NotificationServiceUser;
|
||||||
|
isActive: IsActive;
|
||||||
|
type: Guid;
|
||||||
|
trackingState: NotificationInAppTracking;
|
||||||
|
subject: string;
|
||||||
|
body: string;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
hash: string;
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { Guid } from '@common/types/guid';
|
||||||
|
import { IsActive } from '@notification-service/core/enum/is-active.enum';
|
||||||
|
import { NotificationTemplateChannel } from '@notification-service/core/enum/notification-template-channel.enum';
|
||||||
|
import { NotificationTemplateKind } from '@notification-service/core/enum/notification-template-kind.enum';
|
||||||
|
import { NotificationType } from '@notification-service/core/enum/notification-type.enum';
|
||||||
|
|
||||||
|
export interface NotificationTemplate {
|
||||||
|
id: Guid;
|
||||||
|
channel: NotificationTemplateChannel;
|
||||||
|
notificationType: NotificationType;
|
||||||
|
kind: NotificationTemplateKind;
|
||||||
|
language: string;
|
||||||
|
description: string;
|
||||||
|
value: NotificationTemplateValue;
|
||||||
|
isActive: IsActive;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
hash: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NotificationTemplateValue {
|
||||||
|
subjectText: string;
|
||||||
|
subjectFieldOptions: NotificationFieldOptions;
|
||||||
|
bodyText: string;
|
||||||
|
bodyFieldOptions: NotificationFieldOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NotificationFieldOptions {
|
||||||
|
mandatory?: string[];
|
||||||
|
options?: NotificationFieldInfo[];
|
||||||
|
formatting?: { [key: string]: string };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NotificationFieldInfo {
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NotificationTemplatePersist {
|
||||||
|
id?: Guid;
|
||||||
|
channel: NotificationTemplateChannel;
|
||||||
|
notificationType: NotificationType;
|
||||||
|
kind: NotificationTemplateKind;
|
||||||
|
language: string;
|
||||||
|
description: string;
|
||||||
|
value: NotificationTemplateValue;
|
||||||
|
hash?: string;
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { Guid } from '@common/types/guid';
|
||||||
|
import { ContactType } from '@notification-service/core/enum/contact-type.enum';
|
||||||
|
import { IsActive } from '@notification-service/core/enum/is-active.enum';
|
||||||
|
import { NotificationNotifyState } from '@notification-service/core/enum/notification-notify-state.enum';
|
||||||
|
import { NotificationTrackingProcess } from '@notification-service/core/enum/notification-tracking-process.enum';
|
||||||
|
import { NotificationTrackingState } from '@notification-service/core/enum/notification-tracking-state.enum';
|
||||||
|
import { NotificationType } from '@notification-service/core/enum/notification-type.enum';
|
||||||
|
import { NotificationServiceUser } from '@notification-service/core/model/user.model';
|
||||||
|
|
||||||
|
export interface Notification {
|
||||||
|
id: Guid;
|
||||||
|
user: NotificationServiceUser;
|
||||||
|
isActive: IsActive;
|
||||||
|
type: NotificationType;
|
||||||
|
contactType: ContactType;
|
||||||
|
contactHint: string;
|
||||||
|
data: string;
|
||||||
|
notifyState: NotificationNotifyState;
|
||||||
|
notifiedWith: ContactType;
|
||||||
|
notifiedAt: Date;
|
||||||
|
retryCount: number;
|
||||||
|
trackingState: NotificationTrackingState;
|
||||||
|
trackingProcess: NotificationTrackingProcess;
|
||||||
|
trackingData: string;
|
||||||
|
provenanceType: NotificationType;
|
||||||
|
provenanceRef: string;
|
||||||
|
createdAt: Date;
|
||||||
|
updatedAt: Date;
|
||||||
|
hash: string;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { NotificationServicePermission } from '@notification-service/core/enum/permission.enum';
|
||||||
|
|
||||||
|
export interface NotificationServiceAccount {
|
||||||
|
isAuthenticated: boolean;
|
||||||
|
permissions: NotificationServicePermission[];
|
||||||
|
}
|
|
@ -0,0 +1,92 @@
|
||||||
|
import { Guid } from '@common/types/guid';
|
||||||
|
import { ContactType } from '@notification-service/core/enum/contact-type.enum';
|
||||||
|
import { TenantConfigurationType } from '@notification-service/core/enum/tenant-configuration-type.enum';
|
||||||
|
|
||||||
|
export interface TenantConfiguration {
|
||||||
|
id?: Guid;
|
||||||
|
type: TenantConfigurationType;
|
||||||
|
value: string;
|
||||||
|
slackBroadcastData: SlackBroadcastDataContainer;
|
||||||
|
emailClientData: EmailClientConfigurationDataContainer;
|
||||||
|
smsClientData: SmsClientConfigurationDataContainer;
|
||||||
|
notifierListData: NotifierListConfigurationDataContainer;
|
||||||
|
createdAt?: Date;
|
||||||
|
updatedAt?: Date;
|
||||||
|
hash: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Slack Broadcast
|
||||||
|
//
|
||||||
|
export interface SlackBroadcastDataContainer {
|
||||||
|
webhooks: SlackBroadcastWebhookInfo[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TenantConfigurationSlackBroadcastPersist {
|
||||||
|
id?: Guid;
|
||||||
|
hash?: string;
|
||||||
|
webhooks: SlackBroadcastWebhookInfo[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SlackBroadcastWebhookInfo {
|
||||||
|
id: Guid;
|
||||||
|
name: string;
|
||||||
|
webhook: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Email Client Configuration
|
||||||
|
//
|
||||||
|
export interface EmailClientConfigurationDataContainer {
|
||||||
|
requiresCredentials: boolean;
|
||||||
|
enableSSL: boolean;
|
||||||
|
hostServer: string;
|
||||||
|
hostPortNo: number;
|
||||||
|
emailAddress: string;
|
||||||
|
emailUsername: string;
|
||||||
|
emailPassword: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TenantConfigurationEmailClientPersist {
|
||||||
|
id?: Guid;
|
||||||
|
hash?: string;
|
||||||
|
requiresCredentials: boolean;
|
||||||
|
enableSSL: boolean;
|
||||||
|
hostServer: string;
|
||||||
|
hostPortNo: number;
|
||||||
|
emailAddress: string;
|
||||||
|
emailUsername: string;
|
||||||
|
emailPassword: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Sms Client
|
||||||
|
//
|
||||||
|
export interface SmsClientConfigurationDataContainer {
|
||||||
|
applicationId: string;
|
||||||
|
applicationSecret: string;
|
||||||
|
sendAsName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TenantConfigurationSmsClientPersist {
|
||||||
|
id?: Guid;
|
||||||
|
hash?: string;
|
||||||
|
applicationId: string;
|
||||||
|
applicationSecret: string;
|
||||||
|
sendAsName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Notifier List
|
||||||
|
//
|
||||||
|
export interface NotifierListConfigurationDataContainer {
|
||||||
|
notifiers: { [key: string]: ContactType[] };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TenantConfigurationNotifierListPersist {
|
||||||
|
id?: Guid;
|
||||||
|
hash?: string;
|
||||||
|
notifiers: { [key: string]: ContactType[] };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { Guid } from '@common/types/guid';
|
||||||
|
import { ContactType } from '@notification-service/core/enum/contact-type.enum';
|
||||||
|
import { NotificationType } from '@notification-service/core/enum/notification-type.enum';
|
||||||
|
|
||||||
|
export interface UserNotificationPreference {
|
||||||
|
userId?: Guid;
|
||||||
|
type: NotificationType;
|
||||||
|
channel: ContactType;
|
||||||
|
ordinal: number;
|
||||||
|
createdAt?: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserNotificationPreferencePersist {
|
||||||
|
userId?: Guid;
|
||||||
|
notificationPreferences: { [key: string]: ContactType[] };
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { Guid } from '@common/types/guid';
|
||||||
|
import { ContactInfoType } from '@notification-service/core/enum/contact-info-type.enum';
|
||||||
|
import { IsActive } from '@notification-service/core/enum/is-active.enum';
|
||||||
|
|
||||||
|
export interface NotificationServiceUser {
|
||||||
|
id: Guid;
|
||||||
|
isActive?: IsActive;
|
||||||
|
createdAt?: Date;
|
||||||
|
updatedAt?: Date;
|
||||||
|
hash: string;
|
||||||
|
contacts: NotificationServiceContactInfo[];
|
||||||
|
profile: NotificationServiceUserProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NotificationServiceContactInfo {
|
||||||
|
id: Guid;
|
||||||
|
user: NotificationServiceUser;
|
||||||
|
type?: ContactInfoType;
|
||||||
|
isActive?: IsActive;
|
||||||
|
value: string;
|
||||||
|
ordinal: number;
|
||||||
|
createdAt?: Date;
|
||||||
|
updatedAt?: Date;
|
||||||
|
hash: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NotificationServiceUserProfile {
|
||||||
|
id: Guid;
|
||||||
|
timezone: string;
|
||||||
|
culture?: string;
|
||||||
|
language: string;
|
||||||
|
createdAt?: Date;
|
||||||
|
updatedAt?: Date;
|
||||||
|
hash: string;
|
||||||
|
users: NotificationServiceUser[];
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { NotificationType } from '@notification-service/core/enum/notification-type.enum';
|
||||||
|
|
||||||
|
export class NotifierListLookup implements TenantConfigurationFilter {
|
||||||
|
notificationTypes?: NotificationType[];
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TenantConfigurationFilter {
|
||||||
|
notificationTypes?: NotificationType[];
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { Lookup } from '@common/model/lookup';
|
||||||
|
import { Guid } from '@common/types/guid';
|
||||||
|
import { IsActive } from '@notification-service/core/enum/is-active.enum';
|
||||||
|
import { TenantConfigurationType } from '@notification-service/core/enum/tenant-configuration-type.enum';
|
||||||
|
|
||||||
|
export class TenantConfigurationLookup extends Lookup implements TenantConfigurationFilter {
|
||||||
|
ids?: Guid[];
|
||||||
|
excludedIds?: Guid[];
|
||||||
|
isActive?: IsActive[];
|
||||||
|
type?: TenantConfigurationType[];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TenantConfigurationFilter {
|
||||||
|
ids?: Guid[];
|
||||||
|
excludedIds?: Guid[];
|
||||||
|
isActive?: IsActive[];
|
||||||
|
type?: TenantConfigurationType[];
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { Lookup } from '@common/model/lookup';
|
||||||
|
import { Guid } from '@common/types/guid';
|
||||||
|
import { ContactType } from '@notification-service/core/enum/contact-type.enum';
|
||||||
|
import { NotificationType } from '@notification-service/core/enum/notification-type.enum';
|
||||||
|
|
||||||
|
export class UserNotificationPreferenceLookup extends Lookup implements UserNotificationPreferenceFilter {
|
||||||
|
userIds?: Guid[];
|
||||||
|
type?: NotificationType[];
|
||||||
|
channel?: ContactType[];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UserNotificationPreferenceFilter {
|
||||||
|
userIds?: Guid[];
|
||||||
|
type?: NotificationType[];
|
||||||
|
channel?: ContactType[];
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
|
||||||
|
import { BaseHttpV2Service } from '@app/core/services/http/base-http-v2.service';
|
||||||
|
import { FormService } from '@common/forms/form-service';
|
||||||
|
import { HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service';
|
||||||
|
import { UserNotificationPreferenceService } from '@notification-service/services/http/user-notification-preference.service';
|
||||||
|
import { LoggingService } from '@app/core/services/logging/logging-service';
|
||||||
|
import { FilterService } from '@common/modules/text-filter/filter-service';
|
||||||
|
import { PrincipalService } from '@app/core/services/http/principal.service';
|
||||||
|
import { NotificationServiceEnumUtils } from '@notification-service/core/formatting/enum-utils.service';
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// This is shared module that provides all notification service's services. Its imported only once on the AppModule.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
@NgModule({})
|
||||||
|
export class CoreNotificationServiceModule {
|
||||||
|
constructor(@Optional() @SkipSelf() parentModule: CoreNotificationServiceModule) {
|
||||||
|
if (parentModule) {
|
||||||
|
throw new Error(
|
||||||
|
'CoreNotificationServiceModule is already loaded. Import it in the AppModule only');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static forRoot(): ModuleWithProviders<CoreNotificationServiceModule> {
|
||||||
|
return {
|
||||||
|
ngModule: CoreNotificationServiceModule,
|
||||||
|
providers: [
|
||||||
|
BaseHttpV2Service,
|
||||||
|
HttpErrorHandlingService,
|
||||||
|
NotificationServiceEnumUtils,
|
||||||
|
FormService,
|
||||||
|
FilterService,
|
||||||
|
LoggingService,
|
||||||
|
PrincipalService,
|
||||||
|
UserNotificationPreferenceService
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
import { HttpHeaders } from '@angular/common/http';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { ConfigurationService } from '@app/core/services/configuration/configuration.service';
|
||||||
|
import { BaseHttpV2Service } from '@app/core/services/http/base-http-v2.service';
|
||||||
|
import { QueryResult } from '@common/model/query-result';
|
||||||
|
import { Guid } from '@common/types/guid';
|
||||||
|
import { NotifierListConfigurationDataContainer } from '@notification-service/core/model/tenant-configuration.model';
|
||||||
|
import { UserNotificationPreference, UserNotificationPreferencePersist } from '@notification-service/core/model/user-notification-preference.model';
|
||||||
|
import { NotifierListLookup } from '@notification-service/core/query/notifier-list.lookup';
|
||||||
|
import { UserNotificationPreferenceLookup } from '@notification-service/core/query/user-notification-preference.lookup';
|
||||||
|
import { Observable, throwError } from 'rxjs';
|
||||||
|
import { catchError } from 'rxjs/operators';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UserNotificationPreferenceService {
|
||||||
|
|
||||||
|
private get apiBase(): string { return `${this.configurationService.notificationServiceAddress}api/notification/notification-preference`; }
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private configurationService: ConfigurationService,
|
||||||
|
private http: BaseHttpV2Service
|
||||||
|
) { }
|
||||||
|
|
||||||
|
query(q: UserNotificationPreferenceLookup): Observable<QueryResult<UserNotificationPreference>> {
|
||||||
|
const url = `${this.apiBase}/query`;
|
||||||
|
return this.http
|
||||||
|
.post<QueryResult<UserNotificationPreference>>(url, q).pipe(
|
||||||
|
catchError((error: any) => throwError(error)));
|
||||||
|
}
|
||||||
|
|
||||||
|
current(id: Guid, reqFields: string[] = []): Observable<UserNotificationPreference[]> {
|
||||||
|
const url = `${this.apiBase}/user/${id}/current`;
|
||||||
|
const options = { params: { f: reqFields } };
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.get<UserNotificationPreference[]>(url, options).pipe(
|
||||||
|
catchError((error: any) => throwError(error)));
|
||||||
|
}
|
||||||
|
|
||||||
|
getNotifierList(q: NotifierListLookup): Observable<NotifierListConfigurationDataContainer> {
|
||||||
|
const url = `${this.apiBase}/notifier-list/available`;
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.post<NotifierListConfigurationDataContainer>(url, q).pipe(
|
||||||
|
catchError((error: any) => throwError(error)));
|
||||||
|
}
|
||||||
|
|
||||||
|
persist(item: UserNotificationPreferencePersist, totp?: string): Observable<UserNotificationPreference> {
|
||||||
|
const url = `${this.apiBase}/persist`;
|
||||||
|
let headers = new HttpHeaders();
|
||||||
|
// if (totp) { headers = headers.set(this.configurationService.authTotpHeader, totp); }
|
||||||
|
|
||||||
|
return this.http
|
||||||
|
.post<UserNotificationPreference>(url, item, headers ? { headers: headers } : undefined).pipe(
|
||||||
|
catchError((error: any) => throwError(error)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
<div class="main-tab-content row" *ngIf="availableNotifiersKeys" [ngClass]="preferencesNotCompleted() ? 'd-none' : ''">
|
||||||
|
<div class="col-12" *ngFor="let notificationType of availableNotifiersKeys">
|
||||||
|
<div class="row">
|
||||||
|
<mat-list class="col-12" cdkDropList (cdkDropListDropped)="dropped($event, notificationType)">
|
||||||
|
<h3 mat-subheader>{{notificationServiceEnumUtils.toNotificationTypeString(notificationType)}}</h3>
|
||||||
|
<mat-list-item *ngFor="let contactType of availableNotifiers[notificationType]" cdkDrag>
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<mat-icon matListIcon cdkDragHandle>unfold_more</mat-icon>
|
||||||
|
{{notificationServiceEnumUtils.toContactTypeString(contactType)}}
|
||||||
|
</div>
|
||||||
|
</mat-list-item>
|
||||||
|
</mat-list>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col"></div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<button mat-raised-button color="primary" class="rounded-button" (click)="formSubmit()">
|
||||||
|
{{'NOTIFICATION-SERVICE.USER-PROFILE.NOTIFIER-LIST-EDITOR.ACTIONS.SAVE' | translate}}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="main-tab-content row" [ngClass]="preferencesNotPending() ? 'd-none' : ''">
|
||||||
|
<div class="col-12 d-flex justify-content-center">
|
||||||
|
<mat-spinner [diameter]="20"></mat-spinner>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="main-tab-content row" [ngClass]="preferencesNotWithErrors() ? 'd-none' : ''">
|
||||||
|
<div class="col-12">
|
||||||
|
<span>{{ 'NOTIFICATION-SERVICE.USER-PROFILE.NOTIFIER-LIST-EDITOR.MESSAGES.ERROR' | translate}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
|
@ -0,0 +1,158 @@
|
||||||
|
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
|
||||||
|
import { HttpErrorResponse } from '@angular/common/http';
|
||||||
|
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
|
||||||
|
import { FormGroup } from '@angular/forms';
|
||||||
|
import { AuthService } from '@app/core/services/auth/auth.service';
|
||||||
|
import { LoggingService } from '@app/core/services/logging/logging-service';
|
||||||
|
import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
|
||||||
|
import { BaseComponent } from '@common/base/base.component';
|
||||||
|
import { FormService } from '@common/forms/form-service';
|
||||||
|
import { HttpError, HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service';
|
||||||
|
// import { TotpService } from '@idp-service/ui/totp/totp.service';
|
||||||
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { ContactType } from '@notification-service/core/enum/contact-type.enum';
|
||||||
|
import { NotificationTrackingProcess } from '@notification-service/core/enum/notification-tracking-process.enum';
|
||||||
|
import { NotificationType } from '@notification-service/core/enum/notification-type.enum';
|
||||||
|
import { NotificationServiceEnumUtils } from '@notification-service/core/formatting/enum-utils.service';
|
||||||
|
import { UserNotificationPreference } from '@notification-service/core/model/user-notification-preference.model';
|
||||||
|
import { NotifierListLookup } from '@notification-service/core/query/notifier-list.lookup';
|
||||||
|
import { UserNotificationPreferenceService } from '@notification-service/services/http/user-notification-preference.service';
|
||||||
|
import { UserProfileNotifierListEditorModel } from '@notification-service/ui/user-profile/notifier-list/user-profile-notifier-list-editor.model';
|
||||||
|
import { delay, takeUntil } from 'rxjs/operators';
|
||||||
|
import { nameof } from 'ts-simple-nameof';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-user-profile-notifier-list-editor',
|
||||||
|
templateUrl: './user-profile-notifier-list-editor.component.html',
|
||||||
|
styleUrls: ['./user-profile-notifier-list-editor.component.scss']
|
||||||
|
})
|
||||||
|
export class UserProfileNotifierListEditorComponent extends BaseComponent implements OnInit {
|
||||||
|
|
||||||
|
formGroup: FormGroup;
|
||||||
|
editorModel: UserProfileNotifierListEditorModel;
|
||||||
|
availableNotifiers: { [key: string]: ContactType[] } = {};
|
||||||
|
availableNotifiersKeys: NotificationType[];
|
||||||
|
|
||||||
|
notificationTrackingProcess: NotificationTrackingProcess = NotificationTrackingProcess.Pending;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private userNotificationPreferenceService: UserNotificationPreferenceService,
|
||||||
|
private uiNotificationService: UiNotificationService,
|
||||||
|
private language: TranslateService,
|
||||||
|
private httpErrorHandlingService: HttpErrorHandlingService,
|
||||||
|
private authService: AuthService,
|
||||||
|
private formService: FormService,
|
||||||
|
private logger: LoggingService,
|
||||||
|
public notificationServiceEnumUtils: NotificationServiceEnumUtils,
|
||||||
|
// private totpService: TotpService
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.getConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
getConfiguration() {
|
||||||
|
this.formGroup = null;
|
||||||
|
this.userNotificationPreferenceService.getNotifierList(new NotifierListLookup())
|
||||||
|
.pipe(takeUntil(this._destroyed))
|
||||||
|
.subscribe(
|
||||||
|
data => {
|
||||||
|
try {
|
||||||
|
this.availableNotifiers = data.notifiers;
|
||||||
|
this.availableNotifiersKeys = Object.keys(this.availableNotifiers) as NotificationType[];
|
||||||
|
this.getExistingSelections();
|
||||||
|
} catch {
|
||||||
|
this.notificationTrackingProcess = NotificationTrackingProcess.Error;
|
||||||
|
this.logger.error('Could not parse Dataset: ' + data);
|
||||||
|
this.uiNotificationService.snackBarNotification(this.language.instant('COMMONS.ERRORS.DEFAULT'), SnackBarNotificationLevel.Error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error => this.onCallbackError(error)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getExistingSelections() {
|
||||||
|
this.userNotificationPreferenceService.current(this.authService.userId(), [
|
||||||
|
nameof<UserNotificationPreference>(x => x.userId),
|
||||||
|
nameof<UserNotificationPreference>(x => x.type),
|
||||||
|
nameof<UserNotificationPreference>(x => x.channel),
|
||||||
|
nameof<UserNotificationPreference>(x => x.ordinal),
|
||||||
|
])
|
||||||
|
.pipe(takeUntil(this._destroyed)).subscribe(
|
||||||
|
data => {
|
||||||
|
try {
|
||||||
|
if (data.length > 0) {
|
||||||
|
this.orderAvailableItemsbasedOnExistingSelections(data);
|
||||||
|
}
|
||||||
|
this.notificationTrackingProcess = NotificationTrackingProcess.Completed;
|
||||||
|
} catch {
|
||||||
|
this.notificationTrackingProcess = NotificationTrackingProcess.Error;
|
||||||
|
this.logger.error('Could not parse Dataset: ' + data);
|
||||||
|
this.uiNotificationService.snackBarNotification(this.language.instant('COMMONS.ERRORS.DEFAULT'), SnackBarNotificationLevel.Error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error => this.onCallbackError(error)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
orderAvailableItemsbasedOnExistingSelections(notificationPreferences: UserNotificationPreference[]) {
|
||||||
|
if (!notificationPreferences || notificationPreferences.length === 0) { return; }
|
||||||
|
this.availableNotifiersKeys.forEach(key => {
|
||||||
|
const orderedList = [];
|
||||||
|
orderedList.push(...(notificationPreferences.filter(x => x.type === key && this.availableNotifiers[key].includes(x.channel)).sort((n1, n2) => n1.ordinal - n2.ordinal).map(x => x.channel))); // First push the selected ordered values.
|
||||||
|
orderedList.push(...this.availableNotifiers[key].filter(x => !orderedList.includes(x))); //Then push the rest items.
|
||||||
|
this.availableNotifiers[key] = orderedList;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
formSubmit(): void {
|
||||||
|
this.persist();
|
||||||
|
}
|
||||||
|
|
||||||
|
private persist() {
|
||||||
|
const persistValue = { notificationPreferences: this.availableNotifiers, userId: this.authService.userId() };
|
||||||
|
|
||||||
|
this.userNotificationPreferenceService.persist(persistValue)
|
||||||
|
.pipe(takeUntil(this._destroyed))
|
||||||
|
.subscribe(
|
||||||
|
response => this.onCallbackSuccess(),
|
||||||
|
error => this.onCallbackError(error)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onCallbackSuccess(): void {
|
||||||
|
this.uiNotificationService.snackBarNotification(this.language.instant('COMMONS.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success);
|
||||||
|
this.getConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
onCallbackError(errorResponse: HttpErrorResponse) {
|
||||||
|
this.notificationTrackingProcess = NotificationTrackingProcess.Error;
|
||||||
|
|
||||||
|
const error: HttpError = this.httpErrorHandlingService.getError(errorResponse);
|
||||||
|
if (error.statusCode === 400) {
|
||||||
|
} else {
|
||||||
|
this.uiNotificationService.snackBarNotification(error.getMessagesString(), SnackBarNotificationLevel.Warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clearErrorModel() {
|
||||||
|
this.editorModel.validationErrorModel.clear();
|
||||||
|
this.formService.validateAllFormFields(this.formGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
dropped(event: CdkDragDrop<string[]>, type: NotificationType) {
|
||||||
|
moveItemInArray(this.availableNotifiers[type], event.previousIndex, event.currentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
preferencesNotPending(): boolean {
|
||||||
|
return ! (this.notificationTrackingProcess === NotificationTrackingProcess.Pending);
|
||||||
|
}
|
||||||
|
preferencesNotCompleted(): boolean {
|
||||||
|
return ! (this.notificationTrackingProcess === NotificationTrackingProcess.Completed);
|
||||||
|
}
|
||||||
|
preferencesNotWithErrors(): boolean {
|
||||||
|
return ! (this.notificationTrackingProcess === NotificationTrackingProcess.Error);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
|
||||||
|
import { BackendErrorValidator } from '@common/forms/validation/custom-validator';
|
||||||
|
import { ValidationErrorModel } from '@common/forms/validation/error-model/validation-error-model';
|
||||||
|
import { Validation, ValidationContext } from '@common/forms/validation/validation-context';
|
||||||
|
import { Guid } from '@common/types/guid';
|
||||||
|
import { ContactType } from '@notification-service/core/enum/contact-type.enum';
|
||||||
|
import { NotificationType } from '@notification-service/core/enum/notification-type.enum';
|
||||||
|
import { UserNotificationPreferencePersist } from '@notification-service/core/model/user-notification-preference.model';
|
||||||
|
|
||||||
|
export class UserProfileNotifierListEditorModel implements UserNotificationPreferencePersist {
|
||||||
|
userId?: Guid;
|
||||||
|
notificationPreferences: { [key: string]: ContactType[] };
|
||||||
|
|
||||||
|
public validationErrorModel: ValidationErrorModel = new ValidationErrorModel();
|
||||||
|
protected formBuilder: FormBuilder = new FormBuilder();
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
public fromModel(userId: Guid, notificationPreferences: { [key: string]: ContactType[] }): UserProfileNotifierListEditorModel {
|
||||||
|
this.userId = userId;
|
||||||
|
this.notificationPreferences = notificationPreferences;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildForm(context: ValidationContext = null, disabled: boolean = false, availableNotificationTypes: NotificationType[]): FormGroup {
|
||||||
|
if (context == null) { context = this.createValidationContext(); }
|
||||||
|
|
||||||
|
const notificationPreferencesFormGroup = this.formBuilder.group({});
|
||||||
|
availableNotificationTypes.forEach(type => {
|
||||||
|
notificationPreferencesFormGroup.addControl(type, new FormControl(this.notificationPreferences ? this.notificationPreferences[type] : undefined));
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.formBuilder.group({
|
||||||
|
userId: [{ value: this.userId, disabled: disabled }, context.getValidation('userId').validators],
|
||||||
|
notificationPreferences: notificationPreferencesFormGroup,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createValidationContext(): ValidationContext {
|
||||||
|
const baseContext: ValidationContext = new ValidationContext();
|
||||||
|
const baseValidationArray: Validation[] = new Array<Validation>();
|
||||||
|
|
||||||
|
baseValidationArray.push({ key: 'userId', validators: [BackendErrorValidator(this.validationErrorModel, 'UserId')] });
|
||||||
|
|
||||||
|
baseContext.validation = baseValidationArray;
|
||||||
|
return baseContext;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { DragDropModule } from '@angular/cdk/drag-drop';
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonFormsModule } from '@common/forms/common-forms.module';
|
||||||
|
import { CommonUiModule } from '@common/ui/common-ui.module';
|
||||||
|
import { CoreNotificationServiceModule } from '@notification-service/services/core-service.module';
|
||||||
|
// import { TotpModule } from '@idp-service/ui/totp/totp.module';
|
||||||
|
import { UserProfileNotifierListEditorComponent } from '@notification-service/ui/user-profile/notifier-list/user-profile-notifier-list-editor.component';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonUiModule,
|
||||||
|
CommonFormsModule,
|
||||||
|
DragDropModule,
|
||||||
|
CoreNotificationServiceModule.forRoot(),
|
||||||
|
// TotpModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
UserProfileNotifierListEditorComponent
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
UserProfileNotifierListEditorComponent
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class UserProfileNotifierListModule { }
|
|
@ -27,6 +27,9 @@
|
||||||
],
|
],
|
||||||
"@annotation-service/*":[
|
"@annotation-service/*":[
|
||||||
"./annotation-service/*"
|
"./annotation-service/*"
|
||||||
|
],
|
||||||
|
"@notification-service/*":[
|
||||||
|
"./notification-service/*"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"useDefineForClassFields": false
|
"useDefineForClassFields": false
|
||||||
|
|
Loading…
Reference in New Issue