From 391388f503ddec681512e71649791c456a55838d Mon Sep 17 00:00:00 2001 From: "k.triantafyllou" Date: Thu, 4 Mar 2021 11:32:57 +0000 Subject: [PATCH] [Library | Trunk]: Notifications for development git-svn-id: https://svn.driver.research-infrastructures.eu/driver/dnet40/modules/uoa-services-library/trunk/ng-openaire-library/src/app@60572 d315682c-612b-4755-9ff5-7f18f6832af3 --- .../page-help-content-form.component.ts | 2 +- .../users/role-users/role-users.component.ts | 25 ++- .../users/role-users/role-users.module.ts | 3 +- .../notification-user.component.css | 24 +++ .../notification-user.component.ts | 31 +++ .../notification-user.module.ts | 12 ++ notifications/notification-utils.ts | 56 ++++++ notifications/notification.service.ts | 54 ++++++ .../notification-sidebar.component.css | 115 +++++++++++ .../notifications-sidebar.component.ts | 123 ++++++++++++ .../notifications-sidebar.module.ts | 20 ++ notifications/notifications.ts | 31 +++ .../notify-form/notify-form.component.ts | 181 ++++++++++++++++++ .../notify-form/notify-form.module.ts | 16 ++ role-verification/role-verification.module.ts | 4 +- 15 files changed, 690 insertions(+), 7 deletions(-) create mode 100644 notifications/notification-user/notification-user.component.css create mode 100644 notifications/notification-user/notification-user.component.ts create mode 100644 notifications/notification-user/notification-user.module.ts create mode 100644 notifications/notification-utils.ts create mode 100644 notifications/notification.service.ts create mode 100644 notifications/notifications-sidebar/notification-sidebar.component.css create mode 100644 notifications/notifications-sidebar/notifications-sidebar.component.ts create mode 100644 notifications/notifications-sidebar/notifications-sidebar.module.ts create mode 100644 notifications/notifications.ts create mode 100644 notifications/notify-form/notify-form.component.ts create mode 100644 notifications/notify-form/notify-form.module.ts diff --git a/dashboard/helpTexts/page-help-content-form.component.ts b/dashboard/helpTexts/page-help-content-form.component.ts index d609679c..c2207a6a 100644 --- a/dashboard/helpTexts/page-help-content-form.component.ts +++ b/dashboard/helpTexts/page-help-content-form.component.ts @@ -37,7 +37,7 @@ export class PageContentFormComponent implements OnInit { public errorMessage: string = ''; @Input() updateErrorMessage: string = ''; private subs: Subscription[] = []; - private pageHelpContent: PageHelpContent; + public pageHelpContent: PageHelpContent; constructor(private route: ActivatedRoute, private _router: Router, private _fb: FormBuilder, private _helpContentService: HelpContentService) { } diff --git a/dashboard/users/role-users/role-users.component.ts b/dashboard/users/role-users/role-users.component.ts index bfe66e12..a6420e6c 100644 --- a/dashboard/users/role-users/role-users.component.ts +++ b/dashboard/users/role-users/role-users.component.ts @@ -9,6 +9,7 @@ import {Role, Session, User} from "../../../login/utils/helper.class"; import {UserManagementService} from "../../../services/user-management.service"; import {Router} from "@angular/router"; import {StringUtils} from "../../../utils/string-utils.class"; +import {NotificationService} from "../../../notifications/notification.service"; declare var UIkit; @@ -54,15 +55,16 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges { constructor(private userRegistryService: UserRegistryService, private userManagementService: UserManagementService, + private notificationService: NotificationService, private router: Router, private fb: FormBuilder) { } ngOnInit() { - this.updateLists(); - this.userManagementService.getUserInfo().subscribe(user => { - this.user = user; - }); + this.updateLists(); + this.userManagementService.getUserInfo().subscribe(user => { + this.user = user; + }); } ngOnChanges(changes: SimpleChanges) { @@ -207,6 +209,21 @@ export class RoleUsersComponent implements OnInit, OnDestroy, OnChanges { if (!this.pending.includes(this.invited.value)) { this.pending.push(this.invited.value); } + if(this.notificationFn) { + this.subs.push(this.notificationService.sendNotification(this.notificationFn(this.name, this.invited.value, this.role, invitation)).subscribe(notification => { + UIkit.notification('A notification has been sent successfully', { + status: 'success', + timeout: 6000, + pos: 'bottom-right' + }); + }, error => { + UIkit.notification('An error has occurred. Please try again later', { + status: 'danger', + timeout: 6000, + pos: 'bottom-right' + }); + })); + } UIkit.notification(StringUtils.capitalize(this.role) + ' invitation to ' + this.selectedUser + ' has been sent', { status: 'success', timeout: 6000, diff --git a/dashboard/users/role-users/role-users.module.ts b/dashboard/users/role-users/role-users.module.ts index 2fcc8ff6..af01d69a 100644 --- a/dashboard/users/role-users/role-users.module.ts +++ b/dashboard/users/role-users/role-users.module.ts @@ -10,9 +10,10 @@ import {IconsModule} from "../../../utils/icons/icons.module"; import {InputModule} from "../../../sharedComponents/input/input.module"; import {PageContentModule} from "../../sharedComponents/page-content/page-content.module"; import {SafeHtmlPipeModule} from "../../../utils/pipes/safeHTMLPipe.module"; +import {NotifyFormModule} from "../../../notifications/notify-form/notify-form.module"; @NgModule({ - imports: [CommonModule, AlertModalModule, ReactiveFormsModule, LoadingModule, IconsModule, InputModule, PageContentModule, SafeHtmlPipeModule], + imports: [CommonModule, AlertModalModule, ReactiveFormsModule, LoadingModule, IconsModule, InputModule, PageContentModule, SafeHtmlPipeModule, NotifyFormModule], declarations: [RoleUsersComponent], exports: [RoleUsersComponent] }) diff --git a/notifications/notification-user/notification-user.component.css b/notifications/notification-user/notification-user.component.css new file mode 100644 index 00000000..5bbfc101 --- /dev/null +++ b/notifications/notification-user/notification-user.component.css @@ -0,0 +1,24 @@ +svg:not(.outlined) circle{ + fill: currentColor; + stroke: currentColor; +} + +svg:not(.outlined) text { + fill: white; + stroke: white; +} + + +svg.outlined circle{ + fill: white; + stroke: currentColor; +} + +svg.outlined text { + fill: currentColor; + stroke: currentColor; +} + +svg { + user-select: none; +} diff --git a/notifications/notification-user/notification-user.component.ts b/notifications/notification-user/notification-user.component.ts new file mode 100644 index 00000000..3582eff4 --- /dev/null +++ b/notifications/notification-user/notification-user.component.ts @@ -0,0 +1,31 @@ +import {Component, Input, OnInit} from "@angular/core"; + +@Component({ + selector: 'notification-user', + template: ` + + + + {{firstLetters}} + + + `, + styleUrls: ['notification-user.component.css'] +}) +export class NotificationUserComponent implements OnInit{ + @Input() + public name: string; + @Input() + public surname: string; + @Input() + public colorClass = 'portal-color'; + @Input() + public outline: boolean = false; + public firstLetters: string; + + ngOnInit() { + if(this.name && this.surname) { + this.firstLetters = this.name.charAt(0) + this.surname.charAt(0); + } + } +} diff --git a/notifications/notification-user/notification-user.module.ts b/notifications/notification-user/notification-user.module.ts new file mode 100644 index 00000000..36879f6c --- /dev/null +++ b/notifications/notification-user/notification-user.module.ts @@ -0,0 +1,12 @@ +import {NgModule} from "@angular/core"; +import {CommonModule} from "@angular/common"; +import {NotificationUserComponent} from "./notification-user.component"; + +@NgModule({ + imports: [CommonModule], + declarations: [NotificationUserComponent], + exports: [NotificationUserComponent] +}) +export class NotificationUserModule { + +} diff --git a/notifications/notification-utils.ts b/notifications/notification-utils.ts new file mode 100644 index 00000000..acf328da --- /dev/null +++ b/notifications/notification-utils.ts @@ -0,0 +1,56 @@ +import {Notification} from "./notifications"; +import {HelperFunctions} from "../utils/HelperFunctions.class"; +import {Composer} from "../utils/email/composer"; + +export class NotificationUtils { + public static CREATE_STAKEHOLDER: Notification = new Notification('CREATE', ['monitor'], 'User ((__user__)) has created a new profile', 'stakeholder') + public static EDIT_STAKEHOLDER: Notification = new Notification('EDIT', ['monitor'], 'User ((__user__)) has updated ((__stakeholder__)) profile', 'stakeholder') + public static CREATE_INDICATOR: Notification = new Notification('CREATE', ['monitor'], 'User ((__user__)) has created a new indicator in ((__stakeholder__)) profile', 'indicator'); + public static EDIT_INDICATOR: Notification = new Notification('EDIT', ['monitor'], 'User ((__user__)) has updated an indicator in ((__stakeholder__)) profile', 'indicator'); + public static DELETE_INDICATOR: Notification = new Notification('DELETE', ['monitor'], 'User ((__user__)) has deleted an indicator in ((__stakeholder__)) profile', 'indicator'); + public static INVITE_MONITOR_MANAGER: Notification = new Notification('INVITE_MANAGER', ['monitor'], null, 'user'); + public static INVITE_MONITOR_MEMBER: Notification = new Notification('INVITE_MEMBER', ['monitor'], null, 'user'); + + public static createStakeholder(user: string): Notification { + let notification: Notification = HelperFunctions.copy(this.CREATE_STAKEHOLDER); + notification.message = notification.message.replace('((__user__))', user); + return notification; + } + + public static editStakeholder(user: string, stakeholder: string): Notification { + let notification: Notification = HelperFunctions.copy(this.EDIT_STAKEHOLDER); + notification.message = notification.message.replace('((__user__))', user); + notification.message = notification.message.replace('((__stakeholder__))', stakeholder); + return notification; + } + + public static createIndicator(user: string, stakeholder: string): Notification { + let notification: Notification = HelperFunctions.copy(this.CREATE_INDICATOR); + notification.message = notification.message.replace('((__user__))', user); + notification.message = notification.message.replace('((__stakeholder__))', stakeholder); + return notification; + } + + public static editIndicator(user: string, stakeholder: string): Notification { + let notification: Notification = HelperFunctions.copy(this.EDIT_INDICATOR); + notification.message = notification.message.replace('((__user__))', user); + notification.message = notification.message.replace('((__stakeholder__))', stakeholder); + return notification; + } + + public static deleteIndicator(user: string, stakeholder: string): Notification { + let notification: Notification = HelperFunctions.copy(this.DELETE_INDICATOR); + notification.message = notification.message.replace('((__user__))', user); + notification.message = notification.message.replace('((__stakeholder__))', stakeholder); + return notification; + } + + public static invite(name: string,role: "manager" | "member", user, invitation: string): Notification { + let notification: Notification = HelperFunctions.copy(this.INVITE_MONITOR_MANAGER); + if(role === "member") { + notification = HelperFunctions.copy(this.INVITE_MONITOR_MEMBER); + } + notification.message = Composer.composeMessageForMonitorDashboard(name, role, user, invitation); + return notification; + } +} diff --git a/notifications/notification.service.ts b/notifications/notification.service.ts new file mode 100644 index 00000000..28dc496e --- /dev/null +++ b/notifications/notification.service.ts @@ -0,0 +1,54 @@ +import {Injectable} from "@angular/core"; +import {HttpClient} from "@angular/common/http"; +import {properties} from "../../../environments/environment"; +import {Observable} from "rxjs"; +import {Notification, NotificationUser} from "./notifications"; +import {CustomOptions} from "../services/servicesUtils/customOptions.class"; +import {not} from "rxjs/internal-compatibility"; +import {map} from "rxjs/operators"; + +@Injectable({ + providedIn: "root" +}) +export class NotificationService { + + + constructor(private httpClient: HttpClient) { + } + + public getAllNotifications(): Observable { + return this.httpClient.get(properties.notificationsAPIURL + 'all', CustomOptions.registryOptions()).pipe(map(notifications => { + notifications.forEach(notification => { + this.formatNotification(notification); + }) + return notifications; + })); + } + + public getNotifications(service: string): Observable { + return this.httpClient.get(properties.notificationsAPIURL + encodeURIComponent(service), CustomOptions.registryOptions()).pipe(map(notifications => { + notifications.forEach(notification => { + this.formatNotification(notification); + }) + return notifications; + })); + } + + public sendNotification(notification: Notification): Observable { + return this.httpClient.post(properties.notificationsAPIURL + 'save', notification, CustomOptions.registryOptions()); + } + + public readNotification(id: string): Observable { + return this.httpClient.put(properties.notificationsAPIURL + encodeURIComponent(id), null, CustomOptions.registryOptions()); + } + + private formatNotification(notification: Notification): Notification { + if (notification.title) { + notification.preview = notification.title; + } else { + notification.preview = notification.message.replace(/<[^>]*>/g, ''); + notification.preview = notification.preview.replace(/(\r\n|\n|\r| +(?= ))|\s\s+/gm, " "); + } + return notification; + } +} diff --git a/notifications/notifications-sidebar/notification-sidebar.component.css b/notifications/notifications-sidebar/notification-sidebar.component.css new file mode 100644 index 00000000..a624bb10 --- /dev/null +++ b/notifications/notifications-sidebar/notification-sidebar.component.css @@ -0,0 +1,115 @@ +#notifications-switcher { + top: 250px !important; + position: fixed; + height: 36px; + background-color: var(--portal-main-color); + color: var(--portal-main-contrast); + border-radius: 4px 0 0 4px; + cursor: pointer; + padding: 4px; + box-shadow: -2px 2px 5px rgba(0, 0, 0, .26); + box-sizing: border-box; + right: 0; + z-index: 980; +} + +#notifications-switcher #notifications-count { + position: absolute; + top: 0; + left: 0; + font-size: 10px; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + height: 14px; + border-radius: 50%; + padding: 1px 5px; +} + +#notifications .uk-offcanvas-bar { + background-color: white; + color: #1a1a1a; + font-size: 14px; + top: 100px; + padding: 45px 0; + border: 1px solid var(--portal-main-color); + width: 550px; +} + +#notifications .uk-offcanvas-flip .uk-offcanvas-bar { + right: -550px; +} + +#notifications .uk-offcanvas-bar .text-small { + font-size: 12px; +} + +#notifications .uk-offcanvas-bar h5, #notifications .uk-offcanvas-bar h6 { + color: #1a1a1a; +} + +#notifications button.notification-close, #notifications button.notification-close:focus { + border-radius: 4px; + background-color: #F0F0F0; + color: #76706B; + border: none; + outline: none; +} + +#notifications button.notification-close:hover, #notifications button.notification-close:focus { + color: #1a1a1a; +} + +#notifications .notification-list { + padding: 0 0 0 45px; +} + +#notifications .notification-list:not(:last-child) { + height: 500px; + border-bottom: 1px solid #E4E4E4; +} + +#notifications .notification-list ul { + overflow: auto; + padding: 10px 45px 10px 0; + height: calc(100% - 66px); +} + +#notifications .notification-list ul > li:nth-child(n+2){ + margin-top: 15px; +} + +#notifications .notify { + padding: 20px 45px; +} + +#notifications .notification { + padding: 0 45px; +} + +#notifications .uk-offcanvas-bar a { + color: #2D72D6 ; +} + +#notifications .uk-offcanvas-bar a:hover { + color: var(--portal-main-color); +} + +#notifications .uk-offcanvas-bar .uk-button-secondary { + background-color: #4687e6; + color: #fff; + border: 1px solid transparent; +} + +#notifications .uk-offcanvas-bar .uk-button-secondary:focus, #notifications .uk-offcanvas-bar .uk-button-secondary:hover { + background-color: transparent; + color: #4687e6; + border-color: #4687e6; +} + +#notifications .uk-offcanvas-bar .uk-button-secondary:disabled { + background-color: transparent; + color: #bfbfbf; + border: 1px solid #ededed; + background-image: none; + box-shadow: none; +} diff --git a/notifications/notifications-sidebar/notifications-sidebar.component.ts b/notifications/notifications-sidebar/notifications-sidebar.component.ts new file mode 100644 index 00000000..38737274 --- /dev/null +++ b/notifications/notifications-sidebar/notifications-sidebar.component.ts @@ -0,0 +1,123 @@ +import {Component, Input, OnDestroy, OnInit, ViewEncapsulation} from "@angular/core"; +import {Notification} from "../notifications"; +import {NotificationService} from "../notification.service"; +import {Subscription} from "rxjs"; +import {User} from "../../login/utils/helper.class"; +import {Dates} from "../../utils/string-utils.class"; +import {Option} from "../../sharedComponents/input/input.component"; + +@Component({ + selector: 'notification-sidebar', + template: ` +
+ + + {{unreadCount}} + +
+
+
+ + +
+
Notifications
+
No notifications
+
    +
  • +
    + +
    +
    +
    +

    + {{notification.preview}} +

    +
    +
    + +
    +
    + {{getDate(notification.date)}} +
    +
    +
  • +
+
+
+
+
+
+ + + +
{{notification.title}}
+
+
+ +
+ {{notification.name + ' ' + notification.surname}}
+ + {{notification.date | date:'medium'}} ({{getDate(notification.date)}}) + +
+
+
+
+
+
+
+ `, + styleUrls: ['notification-sidebar.component.css'], + encapsulation: ViewEncapsulation.None +}) +export class NotificationsSidebarComponent implements OnInit, OnDestroy { + @Input() + public user: User; + public notifications: Notification[] = []; + @Input() + public availableGroups: Option[] = []; + @Input() + public service: string; + public notification: Notification; + private subscriptions: any[] = []; + + constructor(private notificationService: NotificationService) { + } + + ngOnInit() { + this.subscriptions.push(this.notificationService.getNotifications(this.service).subscribe(notifications => { + this.notifications = notifications; + })); + } + + ngOnDestroy() { + this.subscriptions.forEach(subscription => { + if (subscription instanceof Subscription) { + subscription.unsubscribe(); + } + }) + } + + get unreadCount(): number { + return this.notifications.filter(notification => !notification.read).length; + } + + getDate(date: Date): string { + return Dates.timeSince(date); + } + + select(notification: Notification) { + this.notificationService.readNotification(notification._id).subscribe(user => { + notification.read = true; + this.notification = notification; + }); + } + + back(event) { + event.stopPropagation(); + this.notification = null; + } +} diff --git a/notifications/notifications-sidebar/notifications-sidebar.module.ts b/notifications/notifications-sidebar/notifications-sidebar.module.ts new file mode 100644 index 00000000..caef44f5 --- /dev/null +++ b/notifications/notifications-sidebar/notifications-sidebar.module.ts @@ -0,0 +1,20 @@ +import {NgModule} from "@angular/core"; +import {CommonModule} from "@angular/common"; +import {NotificationsSidebarComponent} from "./notifications-sidebar.component"; +import {IconsModule} from "../../utils/icons/icons.module"; +import {IconsService} from "../../utils/icons/icons.service"; +import {arrow_left, bullet, close, mail} from "../../utils/icons/icons"; +import {NotificationUserModule} from "../notification-user/notification-user.module"; +import {NotifyFormModule} from "../notify-form/notify-form.module"; +import {SafeHtmlPipeModule} from "../../utils/pipes/safeHTMLPipe.module"; + +@NgModule({ + imports: [CommonModule, IconsModule, NotificationUserModule, NotifyFormModule, SafeHtmlPipeModule], + declarations: [NotificationsSidebarComponent], + exports: [NotificationsSidebarComponent] +}) +export class NotificationsSidebarModule { + constructor(private iconsService: IconsService) { + this.iconsService.registerIcons([mail, close, bullet, arrow_left]); + } +} diff --git a/notifications/notifications.ts b/notifications/notifications.ts new file mode 100644 index 00000000..4304a6d7 --- /dev/null +++ b/notifications/notifications.ts @@ -0,0 +1,31 @@ +export class Notification { + actionType: string; + services: string[]; + user: string; + name: string; + surname: string; + title?: string; + preview: string; + message: string; + stakeholder: string; + stakeholderType: string; + entity: string; + entityType: string; + date: Date; + groups: string[]; + read: boolean = false; + _id: string; + + + constructor(actionType: string, services: string[], message: string, entityType: string) { + this.actionType = actionType; + this.services = services; + this.message = message; + this.entityType = entityType; + } +} + +export interface NotificationUser { + _id: string, + read: string[] +} diff --git a/notifications/notify-form/notify-form.component.ts b/notifications/notify-form/notify-form.component.ts new file mode 100644 index 00000000..adc34695 --- /dev/null +++ b/notifications/notify-form/notify-form.component.ts @@ -0,0 +1,181 @@ +import {ChangeDetectorRef, Component, Input, OnDestroy, OnInit, ViewChild} from "@angular/core"; +import {FormArray, FormBuilder, FormGroup, Validators} from "@angular/forms"; +import {User} from "../../login/utils/helper.class"; +import {UserManagementService} from "../../services/user-management.service"; +import {of, Subscription} from "rxjs"; +import {NotificationService} from "../notification.service"; +import {Notification} from "../notifications"; +import {InputComponent, Option} from "../../sharedComponents/input/input.component"; +import {properties} from "../../../../environments/environment"; + +declare var UIkit; + +@Component({ + selector: '[notify-form]', + template: ` +
+ + {{label}} +
+
+ +
+
+
+
+ +
+ Send to: +
+ Add a recipient + + {{groups.slice(0, 2).join(', ')}} + + {{groups.length - 2}} more + +
+
+
+
+
+
+ +
+
+
+ + +
+
+
+
+
+ ` +}) +export class NotifyFormComponent implements OnInit, OnDestroy { + @Input() + public label: string = 'Notify Managers'; + public form: FormGroup; + @Input() + public availableGroups: Option[] = null; + @Input() service: string; + public user: User; + public focused: boolean = false; + public groups: string[] = []; + @ViewChild('recipients') recipients: InputComponent; + private notification: Notification; + private subscriptions: any[] = []; + public sending: boolean = false; + + constructor(private fb: FormBuilder, + private cdr: ChangeDetectorRef, + private userManagementService: UserManagementService, + private notificationService: NotificationService) { + } + + ngOnInit() { + this.reset(); + this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => { + this.user = user; + })); + } + + ngOnDestroy() { + this.subscriptions.forEach(subscription => { + if (subscription instanceof Subscription) { + subscription.unsubscribe(); + } + }) + } + + reset(message: string = null) { + if (!this.availableGroups) { + this.form = this.fb.group({ + notify: this.fb.control(properties.environment === 'development'), + message: this.fb.control(message) + }); + this.subscriptions.push(this.form.get('notify').valueChanges.subscribe(value => { + if (value) { + this.form.get('message').markAsUntouched(); + } + })); + } else { + this.form = this.fb.group({ + groups: this.fb.array([]), + message: this.fb.control(message) + }); + this.groups = []; + this.subscriptions.push(this.form.get('groups').valueChanges.subscribe(value => { + this.groups = []; + value.forEach(group => { + this.groups.push(this.availableGroups.find(available => available.value === group).label); + }); + this.cdr.detectChanges(); + })); + } + } + + sendNotification(notification: Notification = null) { + if (this.message) { + if(notification === null) { + notification = new Notification('CUSTOM', [this.service], null, null); + notification.groups = this.groupsAsFromArray.value; + this.sending = true; + } + this.notification = notification; + this.notification.message = this.form.value.message; + // TODO remove + this.notification.name = this.user.firstname; + this.notification.surname = this.user.lastname; + this.subscriptions.push(this.notificationService.sendNotification(this.notification).subscribe(notification => { + this.sending = false; + UIkit.notification('A notification has been sent successfully', { + status: 'success', + timeout: 6000, + pos: 'bottom-right' + }); + this.reset(); + }, error => { + this.sending = false; + UIkit.notification('An error has occurred. Please try again later', { + status: 'danger', + timeout: 6000, + pos: 'bottom-right' + }); + this.reset(); + })); + } + } + + get groupsAsFromArray(): FormArray { + return this.form.get('groups')?(this.form.get('groups')):null; + } + + get message(): string { + if ((this.form.get('notify') && !this.form.get('notify').value) || (this.groupsAsFromArray && this.groupsAsFromArray.length === 0)) { + return null; + } + return this.form.get('message').value; + } + + onFocus(event: boolean) { + this.focused = event; + } + + focus(event) { + this.focused = true; + event.stopPropagation(); + this.cdr.detectChanges(); + setTimeout(() => { + this.recipients.searchInput.nativeElement.focus(); + }, 0); + } +} diff --git a/notifications/notify-form/notify-form.module.ts b/notifications/notify-form/notify-form.module.ts new file mode 100644 index 00000000..ea7dda32 --- /dev/null +++ b/notifications/notify-form/notify-form.module.ts @@ -0,0 +1,16 @@ +import {NgModule} from "@angular/core"; +import {NotifyFormComponent} from "./notify-form.component"; +import {CommonModule} from "@angular/common"; +import {MatCheckboxModule} from "@angular/material/checkbox"; +import {ReactiveFormsModule} from "@angular/forms"; +import {InputModule} from "../../sharedComponents/input/input.module"; +import {NotificationUserModule} from "../notification-user/notification-user.module"; + +@NgModule({ + imports: [CommonModule, MatCheckboxModule, ReactiveFormsModule, InputModule, NotificationUserModule], + declarations: [NotifyFormComponent], + exports: [NotifyFormComponent] +}) +export class NotifyFormModule { + +} diff --git a/role-verification/role-verification.module.ts b/role-verification/role-verification.module.ts index 77b13c52..ffc66714 100644 --- a/role-verification/role-verification.module.ts +++ b/role-verification/role-verification.module.ts @@ -5,10 +5,12 @@ import {AlertModalModule} from "../utils/modal/alertModal.module"; import {ReactiveFormsModule} from "@angular/forms"; import {LoadingModule} from "../utils/loading/loading.module"; import {InputModule} from "../sharedComponents/input/input.module"; +import {EmailService} from "../utils/email/email.service"; @NgModule({ imports: [CommonModule, AlertModalModule, ReactiveFormsModule, LoadingModule, InputModule], declarations: [RoleVerificationComponent], - exports: [RoleVerificationComponent] + exports: [RoleVerificationComponent], + providers: [EmailService] }) export class RoleVerificationModule {}