+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dmp-frontend/src/app/ui/inapp-notification/editor/inapp-notification-editor.component.scss b/dmp-frontend/src/app/ui/inapp-notification/editor/inapp-notification-editor.component.scss
new file mode 100644
index 000000000..c916223d1
--- /dev/null
+++ b/dmp-frontend/src/app/ui/inapp-notification/editor/inapp-notification-editor.component.scss
@@ -0,0 +1,7 @@
+.inapp-notification-editor {
+ padding-top: 1em;
+
+ .editor-actions {
+ margin-top: 30px;
+ }
+}
diff --git a/dmp-frontend/src/app/ui/inapp-notification/editor/inapp-notification-editor.component.ts b/dmp-frontend/src/app/ui/inapp-notification/editor/inapp-notification-editor.component.ts
new file mode 100644
index 000000000..60657b505
--- /dev/null
+++ b/dmp-frontend/src/app/ui/inapp-notification/editor/inapp-notification-editor.component.ts
@@ -0,0 +1,130 @@
+import { HttpErrorResponse } from '@angular/common/http';
+import { Component, OnInit } from '@angular/core';
+import { MatDialog } from '@angular/material/dialog';
+import { ActivatedRoute, ParamMap, Router } from '@angular/router';
+import { BaseComponent } from '@common/base/base.component';
+import { FormService } from '@common/forms/form-service';
+import { LoggingService } from '@app/core/services/logging/logging-service';
+import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component';
+import { HttpError, HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service';
+import { Guid } from '@common/types/guid';
+import { TranslateService } from '@ngx-translate/core';
+import { IsActive } from '@app/core/common/enum/is-active.enum';
+import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
+import { map, takeUntil } from 'rxjs/operators';
+import { nameof } from 'ts-simple-nameof';
+import { AuthService } from '@app/core/services/auth/auth.service';
+import { InAppNotification } from '@app/core/model/inapp-notification/inapp-notification.model';
+import { InAppNotificationService } from '@app/core/services/inapp-notification/inapp-notification.service';
+import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
+import { NotificationInAppTracking } from '@app/core/common/enum/notification-inapp-tracking.enum';
+
+@Component({
+ selector: 'app-inapp-notification-editor',
+ templateUrl: './inapp-notification-editor.component.html',
+ styleUrls: ['./inapp-notification-editor.component.scss']
+})
+export class InAppNotificationEditorComponent extends BaseComponent implements OnInit {
+
+ isDeleted = false;
+ isRead = false;
+ isNew = false;
+ isFromDialog = false;
+ inappNotification: InAppNotification;
+
+ constructor(
+ public authService: AuthService,
+ private dialog: MatDialog,
+ private inappNotificationService: InAppNotificationService,
+ private route: ActivatedRoute,
+ private router: Router,
+ private language: TranslateService,
+ public enumUtils: EnumUtils,
+ private formService: FormService,
+ private uiNotificationService: UiNotificationService,
+ private logger: LoggingService,
+ private httpErrorHandlingService: HttpErrorHandlingService
+ ) {
+ super();
+ }
+
+ ngOnInit(): void {
+ this.route.paramMap.pipe(takeUntil(this._destroyed)).subscribe((paramMap: ParamMap) => {
+ const itemId = paramMap.get('id');
+ this.isFromDialog = this.route.snapshot.data ? this.route.snapshot.data['isFromDialog'] as boolean : false;
+
+ if (itemId != null) {
+ this.inappNotificationService.getSingle(Guid.parse(itemId),
+ [
+ nameof
(x => x.id),
+ nameof(x => x.subject),
+ nameof(x => x.body),
+ nameof(x => x.type),
+ nameof(x => x.trackingState),
+ nameof(x => x.isActive),
+ nameof(x => x.hash),
+ nameof(x => x.updatedAt)
+ ])
+ .pipe(map(data => data as InAppNotification), takeUntil(this._destroyed))
+ .subscribe(
+ data => {
+ this.inappNotification = data;
+ this.isDeleted = this.inappNotification.isActive === IsActive.Inactive;
+ this.isRead = this.inappNotification.trackingState === NotificationInAppTracking.Delivered;
+ },
+ error => this.onCallbackError(error)
+ );
+ } else {
+ this.inappNotification = null;
+ }
+ });
+ }
+
+ public markAsRead() {
+ const value = this.inappNotification;
+ this.inappNotificationService.read(value.id).pipe(takeUntil(this._destroyed))
+ .subscribe(
+ complete => this.onCallbackSuccess(),
+ error => this.onCallbackError(error)
+ );
+ // this.clearErrorModel();
+ }
+
+ public delete() {
+ const value = this.inappNotification;
+ if (value.id) {
+ const dialogRef = this.dialog.open(ConfirmationDialogComponent, {
+ maxWidth: '300px',
+ restoreFocus: false,
+ data: {
+ message: this.language.instant('COMMONS.CONFIRMATION-DIALOG.DELETE-ITEM'),
+ confirmButton: this.language.instant('COMMONS.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'),
+ cancelButton: this.language.instant('COMMONS.CONFIRMATION-DIALOG.ACTIONS.CANCEL')
+ }
+ });
+ dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
+ if (result) {
+ this.inappNotificationService.delete(value.id).pipe(takeUntil(this._destroyed))
+ .subscribe(
+ complete => this.onCallbackSuccess(),
+ error => this.onCallbackError(error)
+ );
+ }
+ });
+ }
+ }
+
+ public cancel(): void {
+ this.router.navigate(['/inapp-notifications']);
+ }
+
+ onCallbackSuccess(data?: any): void {
+ this.uiNotificationService.snackBarNotification(this.language.instant('COMMONS.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success);
+ this.router.navigate(['/inapp-notifications']);
+ }
+
+ onCallbackError(errorResponse: HttpErrorResponse) {
+ const error: HttpError = this.httpErrorHandlingService.getError(errorResponse);
+ this.uiNotificationService.snackBarNotification(error.getMessagesString(), SnackBarNotificationLevel.Warning);
+ }
+}
diff --git a/dmp-frontend/src/app/ui/inapp-notification/inapp-notification-routing.module.ts b/dmp-frontend/src/app/ui/inapp-notification/inapp-notification-routing.module.ts
new file mode 100644
index 000000000..4dad21bfa
--- /dev/null
+++ b/dmp-frontend/src/app/ui/inapp-notification/inapp-notification-routing.module.ts
@@ -0,0 +1,35 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { AuthGuard } from '@app/core/auth-guard.service';
+import { InAppNotificationListingComponent } from './listing/inapp-notification-listing.component';
+import { InAppNotificationEditorComponent } from './editor/inapp-notification-editor.component';
+
+const routes: Routes = [
+ {
+ path: '',
+ component: InAppNotificationListingComponent,
+ data: {
+ },
+ canActivate: [AuthGuard]
+ },
+ {
+ path: 'dialog/:id',
+ canActivate: [AuthGuard],
+ data: {
+ isFromDialog: true,
+ },
+ component: InAppNotificationEditorComponent
+ },
+ {
+ path: ':id',
+ canActivate: [AuthGuard],
+ component: InAppNotificationEditorComponent
+ },
+ { path: '**', loadChildren: () => import('@common/modules/page-not-found/page-not-found.module').then(m => m.PageNotFoundModule) },
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+export class InAppNotificationRoutingModule { }
diff --git a/dmp-frontend/src/app/ui/inapp-notification/inapp-notification.module.ts b/dmp-frontend/src/app/ui/inapp-notification/inapp-notification.module.ts
new file mode 100644
index 000000000..33f09eac3
--- /dev/null
+++ b/dmp-frontend/src/app/ui/inapp-notification/inapp-notification.module.ts
@@ -0,0 +1,43 @@
+import { NgModule } from '@angular/core';
+import { CommonFormsModule } from '@common/forms/common-forms.module';
+import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/confirmation-dialog.module';
+import { TextFilterModule } from '@common/modules/text-filter/text-filter.module';
+import { UserSettingsModule } from '@common/modules/user-settings/user-settings.module';
+import { CommonUiModule } from '@common/ui/common-ui.module';
+import { InAppNotificationRoutingModule } from './inapp-notification-routing.module';
+import { InAppNotificationListingComponent } from './listing/inapp-notification-listing.component';
+import { HybridListingModule } from '@common/modules/hybrid-listing/hybrid-listing.module';
+import { InAppNotificationEditorComponent } from './editor/inapp-notification-editor.component';
+import { InAppNotificationListingFiltersComponent } from './listing/filters/inapp-notification-listing-filters.component';
+import { InAppNotificationListingDialogComponent } from './listing-dialog/inapp-notification-listing-dialog.component';
+import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
+import { NotificationInAppTrackingTypePipe } from '@common/formatting/pipes/notification-inapp-tracking-type.pipe';
+import { DatePipe } from '@angular/common';
+import { CommonFormattingModule } from '@common/formatting/common-formatting.module';
+
+@NgModule({
+ imports: [
+ CommonUiModule,
+ CommonFormsModule,
+ ConfirmationDialogModule,
+ HybridListingModule,
+ TextFilterModule,
+ InAppNotificationRoutingModule,
+ UserSettingsModule,
+ CommonFormattingModule
+ ],
+ declarations: [
+ InAppNotificationListingComponent,
+ InAppNotificationEditorComponent,
+ InAppNotificationListingFiltersComponent,
+ InAppNotificationListingDialogComponent
+ ],
+ // entryComponents: [
+ // InAppNotificationListingDialogComponent
+ // ],
+ exports: [
+ InAppNotificationListingComponent,
+ InAppNotificationListingDialogComponent
+ ]
+})
+export class InAppNotificationModule { }
diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing-dialog/inapp-notification-listing-dialog.component.html b/dmp-frontend/src/app/ui/inapp-notification/listing-dialog/inapp-notification-listing-dialog.component.html
new file mode 100644
index 000000000..1ecd1ee51
--- /dev/null
+++ b/dmp-frontend/src/app/ui/inapp-notification/listing-dialog/inapp-notification-listing-dialog.component.html
@@ -0,0 +1,13 @@
+
+
+ drafts
+ mail
+ {{ inappNotification.subject }}
+ {{ inappNotification.createdAt | date : 'short'}}
+
+
+
+ {{'APP.NAVIGATION.ALL-INAPP-NOTIFICATIONS'
+ | translate}}
+
+
diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing-dialog/inapp-notification-listing-dialog.component.scss b/dmp-frontend/src/app/ui/inapp-notification/listing-dialog/inapp-notification-listing-dialog.component.scss
new file mode 100644
index 000000000..7d81257f9
--- /dev/null
+++ b/dmp-frontend/src/app/ui/inapp-notification/listing-dialog/inapp-notification-listing-dialog.component.scss
@@ -0,0 +1,11 @@
+.inapp-notification-listing-dialog {
+ padding-top: 0em;
+
+ .unread{
+ font-weight:bold
+ }
+
+ .secondary-text {
+ color: rgba(0, 0, 0, 0.54);
+ }
+}
diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing-dialog/inapp-notification-listing-dialog.component.ts b/dmp-frontend/src/app/ui/inapp-notification/listing-dialog/inapp-notification-listing-dialog.component.ts
new file mode 100644
index 000000000..b95f85caa
--- /dev/null
+++ b/dmp-frontend/src/app/ui/inapp-notification/listing-dialog/inapp-notification-listing-dialog.component.ts
@@ -0,0 +1,88 @@
+import { HttpErrorResponse } from '@angular/common/http';
+import { Component, Inject, OnInit } from '@angular/core';
+import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
+import { Router } from '@angular/router';
+import { AuthService } from '@app/core/services/auth/auth.service';
+import { HttpError, HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service';
+import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service';
+import { BaseComponent } from '@common/base/base.component';
+import { NotificationInAppTracking } from '@app/core/common/enum/notification-inapp-tracking.enum';
+import { InAppNotification } from '@app/core/model/inapp-notification/inapp-notification.model';
+import { InAppNotificationLookup } from '@app/core/query/inapp-notification.lookup';
+import { InAppNotificationService } from '@app/core/services/inapp-notification/inapp-notification.service';
+import { takeUntil } from 'rxjs/operators';
+import { nameof } from 'ts-simple-nameof';
+
+@Component({
+ selector: 'app-inapp-notification-listing-dialog',
+ templateUrl: './inapp-notification-listing-dialog.component.html',
+ styleUrls: ['./inapp-notification-listing-dialog.component.scss']
+})
+export class InAppNotificationListingDialogComponent extends BaseComponent implements OnInit {
+ public inappNotifications = new Array();
+ public notificationInAppTrackingEnum = NotificationInAppTracking;
+
+ constructor(
+ public dialogRef: MatDialogRef,
+ @Inject(MAT_DIALOG_DATA) public dialogData: any,
+ private inappNotificationService: InAppNotificationService,
+ private router: Router,
+ private uiNotificationService: UiNotificationService,
+ private httpErrorHandlingService: HttpErrorHandlingService,
+ public authService: AuthService,
+ ) {
+ super();
+ }
+
+ ngOnInit() {
+ const lookup = new InAppNotificationLookup();
+ lookup.project = {
+ fields: [
+ nameof(x => x.id),
+ nameof(x => x.subject),
+ nameof(x => x.createdAt),
+ nameof(x => x.trackingState),
+ ]
+ };
+ lookup.page = { offset: 0, size: 10 };
+ lookup.order = { items: ['-' + nameof(x => x.createdAt)] };
+ this.inappNotificationService.query(lookup)
+ .pipe(takeUntil(this._destroyed))
+ .subscribe(
+ data => {
+ this.inappNotifications = data.items;
+ },
+ error => this.onCallbackError(error),
+ );
+ }
+
+ private onCallbackError(errorResponse: HttpErrorResponse) {
+ const error: HttpError = this.httpErrorHandlingService.getError(errorResponse);
+ this.uiNotificationService.snackBarNotification(error.getMessagesString(), SnackBarNotificationLevel.Warning);
+ }
+
+ goToNotification(item: InAppNotification) {
+ if (item.trackingState === NotificationInAppTracking.Stored) {
+ this.inappNotificationService.read(item.id)
+ .pipe(takeUntil(this._destroyed))
+ .subscribe(
+ data => {
+ this.dialogRef.close();
+ this.router.navigate(['/inapp-notifications/dialog/' + item.id]);
+ },
+ error => {
+ this.dialogRef.close();
+ this.router.navigate(['/inapp-notifications/dialog/' + item.id]);
+ },
+ );
+ } else {
+ this.dialogRef.close();
+ this.router.navigate(['/inapp-notifications/dialog/' + item.id]);
+ }
+ }
+
+ goToNotifications() {
+ this.router.navigate(['/inapp-notifications']);
+ this.dialogRef.close();
+ }
+}
diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing/filters/inapp-notification-listing-filters.component.html b/dmp-frontend/src/app/ui/inapp-notification/listing/filters/inapp-notification-listing-filters.component.html
new file mode 100644
index 000000000..7221b4ad0
--- /dev/null
+++ b/dmp-frontend/src/app/ui/inapp-notification/listing/filters/inapp-notification-listing-filters.component.html
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FILTER.TRACKING-STATE' | translate}}
+
+
+ {{enumUtils.toNotificationInAppTrackingString(trackingState)}}
+
+
+
+
+ {{'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FILTER.SHOW-INACTIVE' | translate}}
+
+
+
+
+
diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing/filters/inapp-notification-listing-filters.component.scss b/dmp-frontend/src/app/ui/inapp-notification/listing/filters/inapp-notification-listing-filters.component.scss
new file mode 100644
index 000000000..b533340b2
--- /dev/null
+++ b/dmp-frontend/src/app/ui/inapp-notification/listing/filters/inapp-notification-listing-filters.component.scss
@@ -0,0 +1,22 @@
+.inapp-notification-listing-filters {
+ margin: 1em 0;
+
+ .filter-actions {
+ display: flex;
+ }
+
+ .toggle {
+ font-weight: 400;
+ height: 49px;
+ min-height: 53.59px;
+ background-color: white;
+ border-radius: 0.4em;
+ border: 1px solid #e0e0e0;
+ }
+ }
+
+ :host ::ng-deep .mat-form-field-wrapper {
+ padding-bottom: 0;
+ margin: 1em 0 !important;
+ }
+
\ No newline at end of file
diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing/filters/inapp-notification-listing-filters.component.ts b/dmp-frontend/src/app/ui/inapp-notification/listing/filters/inapp-notification-listing-filters.component.ts
new file mode 100644
index 000000000..3ee0ab0a8
--- /dev/null
+++ b/dmp-frontend/src/app/ui/inapp-notification/listing/filters/inapp-notification-listing-filters.component.ts
@@ -0,0 +1,66 @@
+import { Component, EventEmitter, Input, OnInit, Output, SimpleChanges, OnChanges } from '@angular/core';
+import { BaseComponent } from '@common/base/base.component';
+import { IsActive } from '@app/core/common/enum/is-active.enum';
+import { NotificationInAppTracking } from '@app/core/common/enum/notification-inapp-tracking.enum';
+import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
+import { InAppNotificationFilter } from '@app/core/query/inapp-notification.lookup';
+@Component({
+ selector: 'app-inapp-notification-listing-filters',
+ templateUrl: './inapp-notification-listing-filters.component.html',
+ styleUrls: ['./inapp-notification-listing-filters.component.scss']
+})
+export class InAppNotificationListingFiltersComponent extends BaseComponent implements OnInit, OnChanges {
+
+ @Input() filter: InAppNotificationFilter;
+ @Output() filterChange = new EventEmitter();
+ panelExpanded = false;
+ trackingStates: NotificationInAppTracking[] = this.enumUtils.getEnumValues(NotificationInAppTracking);
+
+ constructor(
+ public enumUtils: EnumUtils
+ ) { super(); }
+
+ ngOnInit() {
+ this.panelExpanded = !this.areHiddenFieldsEmpty();
+ }
+
+ ngOnChanges(changes: SimpleChanges): void {
+ if (changes['filter']) { this.panelExpanded = !this.areHiddenFieldsEmpty(); }
+ }
+
+ onFilterChange() {
+ this.filterChange.emit(this.filter);
+ }
+
+ private areHiddenFieldsEmpty(): boolean {
+ return (!this.filter.isActive || this.filter.isActive.length === 0 || (this.filter.isActive.length === 1 && this.filter.isActive[0] === IsActive.Active));
+ }
+
+ //
+ // Filter getters / setters
+ // Implement here any custom logic regarding how these fields are applied to the lookup.
+ //
+ get like(): string {
+ return this.filter.like;
+ }
+ set like(value: string) {
+ this.filter.like = value;
+ this.filterChange.emit(this.filter);
+ }
+
+ get isActive(): boolean {
+ return this.filter.isActive ? this.filter.isActive.includes(IsActive.Inactive) : true;
+ }
+ set isActive(value: boolean) {
+ this.filter.isActive = value ? [IsActive.Active, IsActive.Inactive] : [IsActive.Active];
+ this.filterChange.emit(this.filter);
+ }
+
+ get trackingState(): NotificationInAppTracking[] {
+ return this.filter.trackingState ? this.filter.trackingState : null;
+ }
+ set trackingState(value: NotificationInAppTracking[]) {
+ this.filter.trackingState = value && value.length > 0 ? value : null;
+ this.filterChange.emit(this.filter);
+ }
+}
diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing/inapp-notification-listing-user-settings.ts b/dmp-frontend/src/app/ui/inapp-notification/listing/inapp-notification-listing-user-settings.ts
new file mode 100644
index 000000000..ae5cf811c
--- /dev/null
+++ b/dmp-frontend/src/app/ui/inapp-notification/listing/inapp-notification-listing-user-settings.ts
@@ -0,0 +1,52 @@
+import { Serializable } from '@common/types/json/serializable';
+import { Lookup } from '@common/model/lookup';
+import { IsActive } from '@app/core/common/enum/is-active.enum';
+import { InAppNotification } from '@app/core/model/inapp-notification/inapp-notification.model';
+import { InAppNotificationLookup } from '@app/core/query/inapp-notification.lookup';
+import { UserSettingsInformation, UserSettingsLookupBuilder } from '@app/core/model/user-settings/user-settings.model';
+import { nameof } from 'ts-simple-nameof';
+
+export class InAppNotificationListingUserSettings implements Serializable, UserSettingsLookupBuilder {
+
+ private like: string;
+ private isActive: IsActive[] = [IsActive.Active];
+ private order: Lookup.Ordering = { items: [nameof(x => x.createdAt)] };
+ private project: Lookup.FieldDirectives = {
+ fields: [
+ nameof(x => x.id),
+ nameof(x => x.subject),
+ nameof(x => x.trackingState),
+ nameof(x => x.createdAt)
+ ]
+ };
+
+ static getUserSettingsInformation(): UserSettingsInformation {
+ return {
+ key: 'InAppNotificationListingUserSettings',
+ type: InAppNotificationListingUserSettings
+ };
+ }
+
+ public fromJSONObject(item: any): InAppNotificationListingUserSettings {
+ this.like = item.like;
+ this.isActive = item.isActive;
+ this.order = item.order;
+ this.project = item.project;
+ return this;
+ }
+
+ public update(lookup: InAppNotificationLookup) {
+ this.like = lookup.like;
+ this.isActive = lookup.isActive;
+ this.order = lookup.order;
+ this.project = lookup.project;
+ }
+
+ public apply(lookup: InAppNotificationLookup): InAppNotificationLookup {
+ lookup.like = this.like;
+ lookup.isActive = this.isActive;
+ lookup.order = this.order;
+ lookup.project = this.project;
+ return lookup;
+ }
+}
diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing/inapp-notification-listing.component.html b/dmp-frontend/src/app/ui/inapp-notification/listing/inapp-notification-listing.component.html
new file mode 100644
index 000000000..b0d2d3803
--- /dev/null
+++ b/dmp-frontend/src/app/ui/inapp-notification/listing/inapp-notification-listing.component.html
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ drafts
+ mail
+
+
+
+
+
diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing/inapp-notification-listing.component.scss b/dmp-frontend/src/app/ui/inapp-notification/listing/inapp-notification-listing.component.scss
new file mode 100644
index 000000000..299948e33
--- /dev/null
+++ b/dmp-frontend/src/app/ui/inapp-notification/listing/inapp-notification-listing.component.scss
@@ -0,0 +1,28 @@
+.inapp-notification-listing {
+ // padding-top: 1em;
+
+ .toggle-row {
+ min-height: 56px;
+ }
+
+ .preview-btn {
+ color: rgb(193, 202, 211);
+ }
+
+ .preview-btn-active {
+ color: black;
+ }
+
+ .view-mode-toggle-container {
+ padding-left: 30px;
+ }
+
+ .mat-fab-bottom-right {
+ top: auto !important;
+ right: 20px !important;
+ bottom: 10px !important;
+ left: auto !important;
+ position: fixed !important;
+ }
+ }
+
\ No newline at end of file
diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing/inapp-notification-listing.component.ts b/dmp-frontend/src/app/ui/inapp-notification/listing/inapp-notification-listing.component.ts
new file mode 100644
index 000000000..6c8503151
--- /dev/null
+++ b/dmp-frontend/src/app/ui/inapp-notification/listing/inapp-notification-listing.component.ts
@@ -0,0 +1,115 @@
+import { Component, OnInit, TemplateRef, ViewChild, EventEmitter, Output, Input } from '@angular/core';
+import { ActivatedRoute, Router } from '@angular/router';
+import { AuthService } from '@app/core/services/auth/auth.service';
+import { QueryParamsService } from '@app/core/services/utilities/query-params.service';
+import { BaseListingComponent } from '@common/base/base-listing-component';
+import { PipeService } from '@common/formatting/pipe.service';
+import { DataTableDateTimeFormatPipe } from '@common/formatting/pipes/date-time-format.pipe';
+import { HttpErrorHandlingService } from '@common/modules/errors/error-handling/http-error-handling.service';
+import { ColumnsChangedEvent, PageLoadEvent } from '@common/modules/hybrid-listing/hybrid-listing.component';
+import { UiNotificationService } from '@app/core/services/notification/ui-notification-service';
+import { InAppNotification } from '@app/core/model/inapp-notification/inapp-notification.model';
+import { InAppNotificationLookup } from '@app/core/query/inapp-notification.lookup';
+import { InAppNotificationService } from '@app/core/services/inapp-notification/inapp-notification.service';
+import { IsActive } from '@app/core/common/enum/is-active.enum';
+import { nameof } from 'ts-simple-nameof';
+import { NotificationInAppTrackingTypePipe } from '@common/formatting/pipes/notification-inapp-tracking-type.pipe';
+import { NotificationInAppTracking } from '@app/core/common/enum/notification-inapp-tracking.enum';
+import { Observable } from 'rxjs';
+import { QueryResult } from '@common/model/query-result';
+
+@Component({
+ selector: 'app-inapp-notification-listing',
+ templateUrl: './inapp-notification-listing.component.html',
+ styleUrls: ['./inapp-notification-listing.component.scss']
+})
+export class InAppNotificationListingComponent extends BaseListingComponent implements OnInit {
+ @ViewChild('readColumnTemplate', { static: true }) readColumnTemplate: TemplateRef;
+ @Input() isPreviewList;
+ @Output() previewModeChange = new EventEmitter();
+
+ userSettingsKey = { key: 'InAppNotificationListingUserSettings' };
+ public notificationInAppTrackingEnum = NotificationInAppTracking;
+
+ constructor(
+ protected router: Router,
+ protected route: ActivatedRoute,
+ protected uiNotificationService: UiNotificationService,
+ protected httpErrorHandlingService: HttpErrorHandlingService,
+ protected queryParamsService: QueryParamsService,
+ private inappNotificationService: InAppNotificationService,
+ public authService: AuthService,
+ private pipeService: PipeService,
+ ) {
+ super(router, route, uiNotificationService, httpErrorHandlingService, queryParamsService);
+ // Lookup setup
+ // Default lookup values are defined in the user settings class.
+ this.lookup = this.initializeLookup();
+ }
+
+ ngOnInit() {
+ super.ngOnInit();
+ }
+
+ protected initializeLookup(): InAppNotificationLookup {
+ const lookup = new InAppNotificationLookup();
+ lookup.metadata = { countAll: true };
+ lookup.page = { offset: 10, size: 10 };
+
+ lookup.isActive = [IsActive.Active];
+ lookup.order = { items: [nameof(x => x.updatedAt)] };
+ lookup.project = {
+ fields: [
+ nameof(x => x.id),
+ nameof(x => x.subject),
+ nameof(x => x.trackingState),
+ nameof(x => x.createdAt)
+ ]
+ };
+
+ return lookup;
+ }
+
+
+ protected setupColumns() {
+ this.gridColumns.push(...[{
+ cellTemplate: this.readColumnTemplate,
+ alwaysShown: true
+ }, {
+ prop: nameof(x => x.subject),
+ sortable: true,
+ languageName: 'INAPP-NOTIFICATION-LISTING.FIELDS.SUBJECT'
+ }, {
+ prop: nameof(x => x.trackingState),
+ sortable: true,
+ languageName: 'INAPP-NOTIFICATION-LISTING.FIELDS.TRACKING-STATE',
+ pipe: this.pipeService.getPipe(NotificationInAppTrackingTypePipe)
+ }, {
+ prop: nameof(x => x.createdAt),
+ sortable: true,
+ languageName: 'INAPP-NOTIFICATION-LISTING.FIELDS.CREATED-AT',
+ pipe: this.pipeService.getPipe(DataTableDateTimeFormatPipe).withFormat('short')
+ }]);
+ }
+
+ onColumnsChanged(event: ColumnsChangedEvent) {
+ // Here are defined the projection fields that always requested from the api.
+ this.lookup.project = {
+ fields: [
+ nameof(x => x.id),
+ nameof(x => x.trackingState),
+ ...event.properties.filter(x => x).map(x => x.toString())
+ ]
+ };
+ this.onPageLoad({ offset: 0 } as PageLoadEvent);
+ }
+
+ protected loadListing() : Observable> {
+ return this.inappNotificationService.query(this.lookup);
+ }
+
+ togglePreviewMode(value: boolean) {
+ this.isPreviewList = value;
+ this.previewModeChange.emit(value);
+ }
+}
diff --git a/dmp-frontend/src/common/formatting/common-formatting.module.ts b/dmp-frontend/src/common/formatting/common-formatting.module.ts
index a16d284a8..2c54e7751 100644
--- a/dmp-frontend/src/common/formatting/common-formatting.module.ts
+++ b/dmp-frontend/src/common/formatting/common-formatting.module.ts
@@ -9,6 +9,7 @@ import { ReferenceTypePipe } from './pipes/reference-type.pipe';
import { ReferenceSourceTypePipe } from './pipes/reference-source-type.pipe';
import { NotificationTemplateChannelPipe } from './pipes/notification-template-channel.pipe';
import { NotificationTemplateKindPipe } from './pipes/notification-template-kind.pipe';
+import { NotificationInAppTrackingTypePipe } from './pipes/notification-inapp-tracking-type.pipe';
//
//
@@ -29,7 +30,8 @@ import { NotificationTemplateKindPipe } from './pipes/notification-template-kind
ReferenceTypePipe,
ReferenceSourceTypePipe,
NotificationTemplateChannelPipe,
- NotificationTemplateKindPipe
+ NotificationTemplateKindPipe,
+ NotificationInAppTrackingTypePipe
],
exports: [
DateFormatPipe,
@@ -44,7 +46,8 @@ import { NotificationTemplateKindPipe } from './pipes/notification-template-kind
ReferenceTypePipe,
ReferenceSourceTypePipe,
NotificationTemplateChannelPipe,
- NotificationTemplateKindPipe
+ NotificationTemplateKindPipe,
+ NotificationInAppTrackingTypePipe
],
providers: [
DateFormatPipe,
@@ -59,7 +62,8 @@ import { NotificationTemplateKindPipe } from './pipes/notification-template-kind
ReferenceTypePipe,
ReferenceSourceTypePipe,
NotificationTemplateChannelPipe,
- NotificationTemplateKindPipe
+ NotificationTemplateKindPipe,
+ NotificationInAppTrackingTypePipe
]
})
export class CommonFormattingModule { }
diff --git a/dmp-frontend/src/common/formatting/pipes/notification-inapp-tracking-type.pipe.ts b/dmp-frontend/src/common/formatting/pipes/notification-inapp-tracking-type.pipe.ts
new file mode 100644
index 000000000..413a7d6b6
--- /dev/null
+++ b/dmp-frontend/src/common/formatting/pipes/notification-inapp-tracking-type.pipe.ts
@@ -0,0 +1,11 @@
+import { Pipe, PipeTransform } from '@angular/core';
+import { EnumUtils } from '@app/core/services/utilities/enum-utils.service';
+
+@Pipe({ name: 'NotificationInAppTrackingTypeFormat' })
+export class NotificationInAppTrackingTypePipe implements PipeTransform {
+ constructor(private enumUtils: EnumUtils) { }
+
+ public transform(value): any {
+ return this.enumUtils.toNotificationInAppTrackingString(value);
+ }
+}