diff --git a/dmp-frontend/src/app/app-routing.module.ts b/dmp-frontend/src/app/app-routing.module.ts index 40d903ebc..798ddb163 100644 --- a/dmp-frontend/src/app/app-routing.module.ts +++ b/dmp-frontend/src/app/app-routing.module.ts @@ -283,11 +283,11 @@ const appRoutes: Routes = [ }, }, { - path: 'inapp-notifications', - loadChildren: () => import('./ui/inapp-notification/inapp-notification.module').then(m => m.InAppNotificationModule), + path: 'mine-notifications', + loadChildren: () => import('./ui/inapp-notification/mine-inapp-notification.module').then(m => m.MineInAppNotificationModule), data: { authContext: { - permissions: [AppPermission.ViewInAppNotificationPage] + permissions: [AppPermission.ViewMineInAppNotificationPage] }, ...BreadcrumbService.generateRouteDataConfiguration({ title: 'BREADCRUMBS.INAPP-NOTIFICATIONS' diff --git a/dmp-frontend/src/app/core/common/enum/permission.enum.ts b/dmp-frontend/src/app/core/common/enum/permission.enum.ts index 5f0772dd1..ab36ba6fb 100644 --- a/dmp-frontend/src/app/core/common/enum/permission.enum.ts +++ b/dmp-frontend/src/app/core/common/enum/permission.enum.ts @@ -34,7 +34,7 @@ export enum AppPermission { ViewTenantPage = 'ViewTenantPage', ViewLanguagePage = "ViewLanguagePage", ViewNotificationTemplatePage = "ViewNotificationTemplatePage", - ViewInAppNotificationPage = "ViewInAppNotificationPage", + ViewMineInAppNotificationPage = "ViewMineInAppNotificationPage", //ReferenceType BrowseReferenceType = "BrowseReferenceType", diff --git a/dmp-frontend/src/app/core/services/inapp-notification/inapp-notification.service.ts b/dmp-frontend/src/app/core/services/inapp-notification/inapp-notification.service.ts index 06dab8b66..b336696bb 100644 --- a/dmp-frontend/src/app/core/services/inapp-notification/inapp-notification.service.ts +++ b/dmp-frontend/src/app/core/services/inapp-notification/inapp-notification.service.ts @@ -57,11 +57,11 @@ export class InAppNotificationService { catchError((error: any) => throwError(error))); } - readAll(): Observable { + readAll(): Observable { const url = `${this.apiBase}/read-all`; return this.http - .post(url, {}).pipe( + .post(url, {}).pipe( catchError((error: any) => throwError(error))); } diff --git a/dmp-frontend/src/app/ui/inapp-notification/editor/inapp-notification-editor.component.html b/dmp-frontend/src/app/ui/inapp-notification/editor/inapp-notification-editor.component.html index fa1640e12..20af9eedf 100644 --- a/dmp-frontend/src/app/ui/inapp-notification/editor/inapp-notification-editor.component.html +++ b/dmp-frontend/src/app/ui/inapp-notification/editor/inapp-notification-editor.component.html @@ -12,7 +12,6 @@
-
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 index 60657b505..ff72fc0b1 100644 --- 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 @@ -71,6 +71,8 @@ export class InAppNotificationEditorComponent extends BaseComponent implements O this.inappNotification = data; this.isDeleted = this.inappNotification.isActive === IsActive.Inactive; this.isRead = this.inappNotification.trackingState === NotificationInAppTracking.Delivered; + + if(!this.isDeleted && !this.isRead) this.markAsRead() }, error => this.onCallbackError(error) ); @@ -115,12 +117,12 @@ export class InAppNotificationEditorComponent extends BaseComponent implements O } public cancel(): void { - this.router.navigate(['/inapp-notifications']); + this.router.navigate(['/mine-notifications']); } onCallbackSuccess(data?: any): void { this.uiNotificationService.snackBarNotification(this.language.instant('COMMONS.SNACK-BAR.SUCCESSFUL-UPDATE'), SnackBarNotificationLevel.Success); - this.router.navigate(['/inapp-notifications']); + this.router.navigate(['/mine-notifications']); } onCallbackError(errorResponse: HttpErrorResponse) { 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/mine-inapp-notification-listing-dialog.component.html similarity index 86% rename from dmp-frontend/src/app/ui/inapp-notification/listing-dialog/inapp-notification-listing-dialog.component.html rename to dmp-frontend/src/app/ui/inapp-notification/listing-dialog/mine-inapp-notification-listing-dialog.component.html index 99d4eb09b..cd85d6d66 100644 --- 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/mine-inapp-notification-listing-dialog.component.html @@ -6,11 +6,11 @@ {{ inappNotification.createdAt | date : 'short'}} - + {{'NAV-BAR.INAPP-NOTIFICATIONS' | translate}} - + {{'NAV-BAR.READ-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/mine-inapp-notification-listing-dialog.component.scss similarity index 100% rename from dmp-frontend/src/app/ui/inapp-notification/listing-dialog/inapp-notification-listing-dialog.component.scss rename to dmp-frontend/src/app/ui/inapp-notification/listing-dialog/mine-inapp-notification-listing-dialog.component.scss 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/mine-inapp-notification-listing-dialog.component.ts similarity index 82% rename from dmp-frontend/src/app/ui/inapp-notification/listing-dialog/inapp-notification-listing-dialog.component.ts rename to dmp-frontend/src/app/ui/inapp-notification/listing-dialog/mine-inapp-notification-listing-dialog.component.ts index 7b51ba03a..23a224bc8 100644 --- 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/mine-inapp-notification-listing-dialog.component.ts @@ -14,16 +14,16 @@ 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'] + selector: 'app-mine-inapp-notification-listing-dialog', + templateUrl: './mine-inapp-notification-listing-dialog.component.html', + styleUrls: ['./mine-inapp-notification-listing-dialog.component.scss'] }) -export class InAppNotificationListingDialogComponent extends BaseComponent implements OnInit { +export class MineInAppNotificationListingDialogComponent extends BaseComponent implements OnInit { public inappNotifications = new Array(); public notificationInAppTrackingEnum = NotificationInAppTracking; constructor( - public dialogRef: MatDialogRef, + public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public dialogData: any, private inappNotificationService: InAppNotificationService, private router: Router, @@ -68,21 +68,21 @@ export class InAppNotificationListingDialogComponent extends BaseComponent imple .subscribe( data => { this.dialogRef.close(); - this.router.navigate(['/inapp-notifications/dialog/' + item.id]); + this.router.navigate(['/mine-notifications/dialog/' + item.id]); }, error => { this.dialogRef.close(); - this.router.navigate(['/inapp-notifications/dialog/' + item.id]); + this.router.navigate(['/mine-notifications/dialog/' + item.id]); }, ); } else { this.dialogRef.close(); - this.router.navigate(['/inapp-notifications/dialog/' + item.id]); + this.router.navigate(['/mine-notifications/dialog/' + item.id]); } } goToNotifications() { - this.router.navigate(['/inapp-notifications']); + this.router.navigate(['/mine-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 deleted file mode 100644 index 3d923d241..000000000 --- a/dmp-frontend/src/app/ui/inapp-notification/listing/filters/inapp-notification-listing-filters.component.html +++ /dev/null @@ -1,30 +0,0 @@ -
- - -
- -
- -
-
-
-
- - {{'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FILTER.TRACKING-STATE' | translate}} - - - {{enumUtils.toNotificationInAppTrackingString(trackingState)}} - - -
- - {{'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FILTER.IS-ACTIVE' | 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 deleted file mode 100644 index b533340b2..000000000 --- a/dmp-frontend/src/app/ui/inapp-notification/listing/filters/inapp-notification-listing-filters.component.scss +++ /dev/null @@ -1,22 +0,0 @@ -.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 deleted file mode 100644 index 0418ee1cc..000000000 --- a/dmp-frontend/src/app/ui/inapp-notification/listing/filters/inapp-notification-listing-filters.component.ts +++ /dev/null @@ -1,73 +0,0 @@ -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; - if (value[0] == 0){ - this.filter.trackingState = [NotificationInAppTracking.Stored]; - } else if(value[0] == 1) { - this.filter.trackingState = [NotificationInAppTracking.Delivered]; - } else { - this.filter.trackingState = null; - } - this.filterChange.emit(this.filter); - } -} diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing/filters/mine-inapp-notification-listing-filters.component.html b/dmp-frontend/src/app/ui/inapp-notification/listing/filters/mine-inapp-notification-listing-filters.component.html new file mode 100644 index 000000000..817a3b1b6 --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/listing/filters/mine-inapp-notification-listing-filters.component.html @@ -0,0 +1,40 @@ +
+ + + + + +
+
+
+

{{'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FILTER.TITLE' | translate}}

+ +
+ +
+ {{'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FILTER.TRACKING-STATE' | translate}} + + {{enumUtils.toNotificationInAppTrackingString(state)}} + + +
+ +
+ + +
+
+
+
+ + +
diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing/filters/mine-inapp-notification-listing-filters.component.scss b/dmp-frontend/src/app/ui/inapp-notification/listing/filters/mine-inapp-notification-listing-filters.component.scss new file mode 100644 index 000000000..3e65f7c04 --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/listing/filters/mine-inapp-notification-listing-filters.component.scss @@ -0,0 +1,20 @@ + +::ng-deep.mat-mdc-menu-panel { + max-width: 100% !important; + height: 100% !important; +} + +:host::ng-deep.mat-mdc-menu-content:not(:empty) { + padding-top: 0 !important; +} + + +.filter-button{ + padding-top: .6rem; + padding-bottom: .6rem; + // .mat-icon{ + // font-size: 1.5em; + // width: 1.2em; + // height: 1.2em; + // } +} diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing/filters/mine-inapp-notification-listing-filters.component.ts b/dmp-frontend/src/app/ui/inapp-notification/listing/filters/mine-inapp-notification-listing-filters.component.ts new file mode 100644 index 000000000..ec69b6278 --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/listing/filters/mine-inapp-notification-listing-filters.component.ts @@ -0,0 +1,93 @@ +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'; +import { nameof } from 'ts-simple-nameof'; +@Component({ + selector: 'app-mine-inapp-notification-listing-filters', + templateUrl: './mine-inapp-notification-listing-filters.component.html', + styleUrls: ['./mine-inapp-notification-listing-filters.component.scss'] +}) +export class MineInAppNotificationListingFiltersComponent extends BaseComponent implements OnInit, OnChanges { + + @Input() readonly filter: InAppNotificationFilter; + @Output() filterChange = new EventEmitter(); + + notificationInAppTrackingEnumValues = this.enumUtils.getEnumValues(NotificationInAppTracking); + + // * State + internalFilters: InAppNotificationListingFilters = this._getEmptyFilters(); + + protected appliedFilterCount: number = 0; + constructor( + public enumUtils: EnumUtils, + ) { super(); } + + ngOnInit() { + } + + ngOnChanges(changes: SimpleChanges): void { + const filterChange = changes[nameof(x => x.filter)]?.currentValue as InAppNotificationFilter; + if (filterChange) { + this.updateFilters() + } + } + + + onSearchTermChange(searchTerm: string): void { + this.applyFilters() + } + + + protected updateFilters(): void { + this.internalFilters = this._parseToInternalFilters(this.filter); + this.appliedFilterCount = this._computeAppliedFilters(this.internalFilters); + } + + protected applyFilters(): void { + const { like, trackingState } = this.internalFilters ?? {} + this.filterChange.emit({ + ...this.filter, + like, + trackingState + }) + } + + + private _parseToInternalFilters(inputFilter: InAppNotificationFilter): InAppNotificationListingFilters { + if (!inputFilter) { + return this._getEmptyFilters(); + } + + let { like, trackingState } = inputFilter; + + return { + like: like, + trackingState: trackingState + } + + } + + private _getEmptyFilters(): InAppNotificationListingFilters { + return { + like: null, + trackingState: null + } + } + + private _computeAppliedFilters(filters: InAppNotificationListingFilters): number { + let count = 0; + return count; + } + + clearFilters() { + this.internalFilters = this._getEmptyFilters(); + } +} + +interface InAppNotificationListingFilters { + like: string; + trackingState: NotificationInAppTracking[]; +} 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 deleted file mode 100644 index ae5cf811c..000000000 --- a/dmp-frontend/src/app/ui/inapp-notification/listing/inapp-notification-listing-user-settings.ts +++ /dev/null @@ -1,52 +0,0 @@ -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 deleted file mode 100644 index b0d2d3803..000000000 --- a/dmp-frontend/src/app/ui/inapp-notification/listing/inapp-notification-listing.component.html +++ /dev/null @@ -1,46 +0,0 @@ -
-
-
-
- -
- - -
- -
-
- - -
-
- -
-
- -
-
- -
-
- - - - - 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 deleted file mode 100644 index 299948e33..000000000 --- a/dmp-frontend/src/app/ui/inapp-notification/listing/inapp-notification-listing.component.scss +++ /dev/null @@ -1,28 +0,0 @@ -.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 deleted file mode 100644 index a5b5264c3..000000000 --- a/dmp-frontend/src/app/ui/inapp-notification/listing/inapp-notification-listing.component.ts +++ /dev/null @@ -1,116 +0,0 @@ -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: 'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FIELDS.SUBJECT' - }, { - prop: nameof(x => x.trackingState), - sortable: true, - languageName: 'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FIELDS.TRACKING-STATE', - pipe: this.pipeService.getPipe(NotificationInAppTrackingTypePipe) - }, { - prop: nameof(x => x.createdAt), - sortable: true, - languageName: 'NOTIFICATION-SERVICE.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> { - console.log(this.lookup); - return this.inappNotificationService.query(this.lookup); - } - - togglePreviewMode(value: boolean) { - this.isPreviewList = value; - this.previewModeChange.emit(value); - } -} diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing/mine-inapp-notification-listing.component.html b/dmp-frontend/src/app/ui/inapp-notification/listing/mine-inapp-notification-listing.component.html new file mode 100644 index 000000000..22ec8c7cf --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/listing/mine-inapp-notification-listing.component.html @@ -0,0 +1,67 @@ +
+
+ +
+
+

{{'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.TITLE' | translate}}

+ + +
+
+ + + + + + + + +
+
+ + + + +
+
+ + {{item?.trackingState | nullifyValue}} +
+
+ + + + {{'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FIELDS.CREATED-AT' | translate}}: + + {{item?.createdAt | dateTimeFormatter : 'short' | nullifyValue}} + + +
+
+
+
+
+ + +
+
+ + + + +
+
+
\ No newline at end of file diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing/mine-inapp-notification-listing.component.scss b/dmp-frontend/src/app/ui/inapp-notification/listing/mine-inapp-notification-listing.component.scss new file mode 100644 index 000000000..977565d41 --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/listing/mine-inapp-notification-listing.component.scss @@ -0,0 +1,61 @@ +.inapp-notification-listing { + margin-top: 1.3rem; + margin-left: 1rem; + margin-right: 2rem; + + .mat-header-row{ + background: #f3f5f8; + } + .mat-card { + margin: 16px 0; + padding: 0px; + } + + .mat-row { + cursor: pointer; + min-height: 4.5em; + } + + mat-row:hover { + background-color: #eef5f6; + } + .mat-fab-bottom-right { + float: right; + z-index: 5; + } + } + .create-btn { + border-radius: 30px; + background-color: var(--secondary-color); + padding-left: 2em; + padding-right: 2em; + // color: #000; + + .button-text{ + display: inline-block; + } + } + + .dlt-btn { + color: rgba(0, 0, 0, 0.54); + } + + .status-chip{ + + border-radius: 20px; + padding-left: 1em; + padding-right: 1em; + padding-top: 0.2em; + font-size: .8em; + } + + .status-chip-finalized{ + color: #568b5a; + background: #9dd1a1 0% 0% no-repeat padding-box; + } + + .status-chip-draft{ + color: #00c4ff; + background: #d3f5ff 0% 0% no-repeat padding-box; + } + \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/inapp-notification/listing/mine-inapp-notification-listing.component.ts b/dmp-frontend/src/app/ui/inapp-notification/listing/mine-inapp-notification-listing.component.ts new file mode 100644 index 000000000..eba6155f3 --- /dev/null +++ b/dmp-frontend/src/app/ui/inapp-notification/listing/mine-inapp-notification-listing.component.ts @@ -0,0 +1,164 @@ +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 { ColumnDefinition, ColumnsChangedEvent, HybridListingComponent, PageLoadEvent } from '@common/modules/hybrid-listing/hybrid-listing.component'; +import { SnackBarNotificationLevel, 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 { Observable } from 'rxjs'; +import { QueryResult } from '@common/model/query-result'; +import { EnumUtils } from '@app/core/services/utilities/enum-utils.service'; +import { TranslateService } from '@ngx-translate/core'; +import { MatDialog } from '@angular/material/dialog'; +import { Guid } from '@common/types/guid'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; +import { takeUntil } from 'rxjs/operators'; + +@Component({ + selector: 'app-mine-inapp-notification-listing', + templateUrl: './mine-inapp-notification-listing.component.html', + styleUrls: ['./mine-inapp-notification-listing.component.scss'] +}) +export class MineInAppNotificationListingComponent extends BaseListingComponent implements OnInit { + publish = false; + userSettingsKey = { key: 'InAppNotificationListingUserSettings' }; + propertiesAvailableForOrder: ColumnDefinition[]; + + @ViewChild('actions', { static: true }) actions?: TemplateRef; + @ViewChild(HybridListingComponent, { static: true }) hybridListingComponent: HybridListingComponent; + + private readonly lookupFields: string[] = [ + nameof(x => x.id), + nameof(x => x.subject), + nameof(x => x.trackingState), + nameof(x => x.createdAt), + nameof(x => x.isActive) + ]; + + rowIdentity = x => x.id; + + 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, + public enumUtils: EnumUtils, + private language: TranslateService, + private dialog: MatDialog + ) { + 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: 0, size: this.ITEMS_PER_PAGE }; + lookup.isActive = [IsActive.Active]; + lookup.order = { items: [this.toDescSortField(nameof(x => x.createdAt))] }; + this.updateOrderUiFields(lookup.order); + + lookup.project = { + fields: this.lookupFields + }; + + return lookup; + } + + protected setupColumns() { + this.gridColumns.push(...[{ + prop: nameof(x => x.subject), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FIELDS.SUBJECT' + }, + { + prop: nameof(x => x.trackingState), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FIELDS.TRACKING-STATE', + pipe: this.pipeService.getPipe(NotificationInAppTrackingTypePipe) + }, + { + prop: nameof(x => x.createdAt), + sortable: true, + languageName: 'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FIELDS.CREATED-AT', + pipe: this.pipeService.getPipe(DataTableDateTimeFormatPipe).withFormat('short') + }, + { + alwaysShown: true, + cellTemplate: this.actions, + maxWidth: 120 + } + ]); + this.propertiesAvailableForOrder = this.gridColumns.filter(x => x.sortable); + } + + // + // Listing Component functions + // + onColumnsChanged(event: ColumnsChangedEvent) { + super.onColumnsChanged(event); + this.onColumnsChangedInternal(event.properties.map(x => x.toString())); + } + + private onColumnsChangedInternal(columns: string[]) { + // Here are defined the projection fields that always requested from the api. + const fields = new Set(this.lookupFields); + this.gridColumns.map(x => x.prop) + .filter(x => !columns?.includes(x as string)) + .forEach(item => { + fields.delete(item as string) + }); + this.lookup.project = { fields: [...fields] }; + this.onPageLoad({ offset: 0 } as PageLoadEvent); + } + + protected loadListing(): Observable> { + return this.inAppNotificationService.query(this.lookup); + } + + public deleteType(id: Guid) { + if (id) { + const dialogRef = this.dialog.open(ConfirmationDialogComponent, { + data: { + isDeleteConfirmation: true, + message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.DELETE-ITEM'), + confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'), + cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL') + } + }); + dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { + if (result) { + this.inAppNotificationService.delete(id).pipe(takeUntil(this._destroyed)) + .subscribe( + complete => this.onCallbackSuccess(), + error => this.onCallbackError(error) + ); + } + }); + } + } + + onCallbackSuccess(): void { + this.uiNotificationService.snackBarNotification(this.language.instant('GENERAL.SNACK-BAR.SUCCESSFUL-DELETE'), SnackBarNotificationLevel.Success); + this.ngOnInit(); + } +} diff --git a/dmp-frontend/src/app/ui/inapp-notification/inapp-notification-routing.module.ts b/dmp-frontend/src/app/ui/inapp-notification/mine-inapp-notification-routing.module.ts similarity index 78% rename from dmp-frontend/src/app/ui/inapp-notification/inapp-notification-routing.module.ts rename to dmp-frontend/src/app/ui/inapp-notification/mine-inapp-notification-routing.module.ts index 4dad21bfa..26530a7e4 100644 --- a/dmp-frontend/src/app/ui/inapp-notification/inapp-notification-routing.module.ts +++ b/dmp-frontend/src/app/ui/inapp-notification/mine-inapp-notification-routing.module.ts @@ -1,13 +1,13 @@ 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 { MineInAppNotificationListingComponent } from './listing/mine-inapp-notification-listing.component'; import { InAppNotificationEditorComponent } from './editor/inapp-notification-editor.component'; const routes: Routes = [ { path: '', - component: InAppNotificationListingComponent, + component: MineInAppNotificationListingComponent, data: { }, canActivate: [AuthGuard] @@ -32,4 +32,4 @@ const routes: Routes = [ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) -export class InAppNotificationRoutingModule { } +export class MineInAppNotificationRoutingModule { } diff --git a/dmp-frontend/src/app/ui/inapp-notification/inapp-notification.module.ts b/dmp-frontend/src/app/ui/inapp-notification/mine-inapp-notification.module.ts similarity index 50% rename from dmp-frontend/src/app/ui/inapp-notification/inapp-notification.module.ts rename to dmp-frontend/src/app/ui/inapp-notification/mine-inapp-notification.module.ts index 7717c1225..30e48d718 100644 --- a/dmp-frontend/src/app/ui/inapp-notification/inapp-notification.module.ts +++ b/dmp-frontend/src/app/ui/inapp-notification/mine-inapp-notification.module.ts @@ -4,15 +4,12 @@ import { ConfirmationDialogModule } from '@common/modules/confirmation-dialog/co 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 { MineInAppNotificationRoutingModule } from './mine-inapp-notification-routing.module'; +import { MineInAppNotificationListingComponent } from './listing/mine-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 { MineInAppNotificationListingFiltersComponent } from './listing/filters/mine-inapp-notification-listing-filters.component'; +import { MineInAppNotificationListingDialogComponent } from './listing-dialog/mine-inapp-notification-listing-dialog.component'; import { CommonFormattingModule } from '@common/formatting/common-formatting.module'; @NgModule({ @@ -22,21 +19,18 @@ import { CommonFormattingModule } from '@common/formatting/common-formatting.mod ConfirmationDialogModule, HybridListingModule, TextFilterModule, - InAppNotificationRoutingModule, + MineInAppNotificationRoutingModule, UserSettingsModule, CommonFormattingModule ], declarations: [ - InAppNotificationListingComponent, + MineInAppNotificationListingComponent, InAppNotificationEditorComponent, - InAppNotificationListingFiltersComponent, - InAppNotificationListingDialogComponent + MineInAppNotificationListingFiltersComponent, + MineInAppNotificationListingDialogComponent ], - // entryComponents: [ - // InAppNotificationListingDialogComponent - // ], exports: [ - InAppNotificationListingComponent, + MineInAppNotificationListingComponent, ] }) -export class InAppNotificationModule { } +export class MineInAppNotificationModule { } diff --git a/dmp-frontend/src/app/ui/navbar/navbar.component.html b/dmp-frontend/src/app/ui/navbar/navbar.component.html index 4602acb15..56a9a3957 100644 --- a/dmp-frontend/src/app/ui/navbar/navbar.component.html +++ b/dmp-frontend/src/app/ui/navbar/navbar.component.html @@ -32,7 +32,7 @@ -
+
diff --git a/dmp-frontend/src/app/ui/navbar/navbar.component.ts b/dmp-frontend/src/app/ui/navbar/navbar.component.ts index 5192c3085..0431fdf2d 100644 --- a/dmp-frontend/src/app/ui/navbar/navbar.component.ts +++ b/dmp-frontend/src/app/ui/navbar/navbar.component.ts @@ -16,7 +16,7 @@ import { StartNewDmpDialogComponent } from '../dmp/new/start-new-dmp-dialogue/st import { FaqDialogComponent } from '../faq/dialog/faq-dialog.component'; import { UserDialogComponent } from './user-dialog/user-dialog.component'; import { DATASETS_ROUTES, DMP_ROUTES, GENERAL_ROUTES } from '../sidebar/sidebar.component'; -import { InAppNotificationListingDialogComponent } from '../inapp-notification/listing-dialog/inapp-notification-listing-dialog.component'; +import { MineInAppNotificationListingDialogComponent } from '../inapp-notification/listing-dialog/mine-inapp-notification-listing-dialog.component'; import { InAppNotificationService } from '@app/core/services/inapp-notification/inapp-notification.service'; import { timer } from 'rxjs'; import { ConfigurationService } from '@app/core/services/configuration/configuration.service'; @@ -37,7 +37,7 @@ export class NavbarComponent extends BaseComponent implements OnInit { currentRoute: string; selectedLanguage: string; private user: User; - inAppNotificationDialog: MatDialogRef = null; + inAppNotificationDialog: MatDialogRef = null; inAppNotificationCount = 0; @Output() sidebarToggled: EventEmitter = new EventEmitter(); @ViewChild(MatMenuTrigger) trigger: MatMenuTrigger; @@ -303,7 +303,7 @@ export class NavbarComponent extends BaseComponent implements OnInit { this.inAppNotificationDialog.close(); } else { this.countUnreadInappNotifications(); - this.inAppNotificationDialog = this.dialog.open(InAppNotificationListingDialogComponent, { + this.inAppNotificationDialog = this.dialog.open(MineInAppNotificationListingDialogComponent, { position: { top: '64px', right: '0px' } diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json index a87e020fc..fffb7922c 100644 --- a/dmp-frontend/src/assets/i18n/en.json +++ b/dmp-frontend/src/assets/i18n/en.json @@ -254,7 +254,8 @@ "LANGUAGES": "Languages", "NEW-LANGUAGE": "New", "EDIT-LANGUAGE": "Edit", - "NOTIFICATION-TEMPLATES": "Notification Templates" + "NOTIFICATION-TEMPLATES": "Notification Templates", + "INAPP-NOTIFICATIONS":"Notifications" }, "COOKIE": { "MESSAGE": "This website uses cookies to enhance the user experience.", @@ -1331,17 +1332,16 @@ }, "NOTIFICATION-SERVICE": { "INAPP-NOTIFICATION-LISTING": { + "TITLE": "Notifications", "FIELDS": { "SUBJECT": "Subject", - "TRACKING-STATE": "Tracking State", - "CREATED-AT": "Created", - "IS-ACTIVE": "Is Active" + "TRACKING-STATE": "State", + "CREATED-AT": "Created" }, "FILTER": { - "MORE-FILTERS": "More filters", - "TRACKING-STATE":"Tracking State", + "TITLE": "Filters", + "TRACKING-STATE":"State", "IS-ACTIVE": "Is Active", - "CHANNEL": "Channel", "CANCEL": "Cancel", "APPLY-FILTERS": "Apply filters" }, @@ -1362,7 +1362,6 @@ }, "ACTIONS": { - "READ": "Read", "CANCEL": "Cancel", "DELETE": "Delete" } @@ -2316,8 +2315,8 @@ "PUBLIC-CONTACT-SUPPORT": "Public Contact Support" }, "NOTIFICATION-INAPP-TRACKING": { - "STORED": "Stored", - "DELIVERED": "Delivered" + "STORED": "Unread", + "DELIVERED": "Read" } }, "ADDRESEARCHERS-EDITOR": {