Merge branch 'dmp-refactoring' of code-repo.d4science.org:MaDgiK-CITE/argos into dmp-refactoring

This commit is contained in:
Efstratios Giannopoulos 2024-01-09 16:02:47 +02:00
commit e123338a2c
14 changed files with 141 additions and 12 deletions

View File

@ -32,7 +32,8 @@ public class TenantScopedEntityManager {
public int getBulkSize() { public int getBulkSize() {
Session session = this.entityManager.unwrap(Session.class); Session session = this.entityManager.unwrap(Session.class);
return session.getJdbcBatchSize(); if (session.getJdbcBatchSize() != null) return session.getJdbcBatchSize();
return 0;
} }
public void setBulkSize(int size) { public void setBulkSize(int size) {

View File

@ -118,6 +118,11 @@ export class ConfigurationService extends BaseComponent {
return this._notificationServiceEnabled; return this._notificationServiceEnabled;
} }
private _inAppNotificationsCountInterval: number;
get inAppNotificationsCountInterval(): number {
return this._inAppNotificationsCountInterval || 3200;
}
public loadConfiguration(): Promise<any> { public loadConfiguration(): Promise<any> {
return new Promise((r, e) => { return new Promise((r, e) => {
// We need to exclude all interceptors here, for the initial configuration request. // We need to exclude all interceptors here, for the initial configuration request.
@ -178,6 +183,7 @@ export class ConfigurationService extends BaseComponent {
this._notificationServiceEnabled = config.notification_service.enabled; this._notificationServiceEnabled = config.notification_service.enabled;
this._notificationServiceAddress = config.notification_service.address; this._notificationServiceAddress = config.notification_service.address;
} }
this._inAppNotificationsCountInterval = config.inAppNotificationsCountInterval;
} }
} }

View File

@ -57,6 +57,14 @@ export class InAppNotificationService {
catchError((error: any) => throwError(error))); catchError((error: any) => throwError(error)));
} }
readAll(): Observable<string> {
const url = `${this.apiBase}/read-all`;
return this.http
.post<string>(url, {}).pipe(
catchError((error: any) => throwError(error)));
}
delete(id: Guid): Observable<InAppNotification> { delete(id: Guid): Observable<InAppNotification> {
const url = `${this.apiBase}/${id}`; const url = `${this.apiBase}/${id}`;
return this.http return this.http

View File

@ -37,7 +37,6 @@ import { CommonFormattingModule } from '@common/formatting/common-formatting.mod
// ], // ],
exports: [ exports: [
InAppNotificationListingComponent, InAppNotificationListingComponent,
InAppNotificationListingDialogComponent
] ]
}) })
export class InAppNotificationModule { } export class InAppNotificationModule { }

View File

@ -6,8 +6,12 @@
<span mat-line class="secondary-text">{{ inappNotification.createdAt | date : 'short'}}</span> <span mat-line class="secondary-text">{{ inappNotification.createdAt | date : 'short'}}</span>
<mat-divider inset *ngIf="!last"></mat-divider> <mat-divider inset *ngIf="!last"></mat-divider>
</a> </a>
<mat-list-item *ngIf="authService.hasPermission(authService.permissionEnum.ViewInAppNotificationPage)"> <mat-list-item class = "mat-list-item-content" *ngIf="authService.hasPermission(authService.permissionEnum.ViewInAppNotificationPage)">
<a (click)="goToNotifications()">{{'APP.NAVIGATION.ALL-INAPP-NOTIFICATIONS' <a (click)="goToNotifications()">{{'NAV-BAR.INAPP-NOTIFICATIONS'
| translate}}</a>
</mat-list-item>
<mat-list-item class = "mat-list-item-content" *ngIf="authService.hasPermission(authService.permissionEnum.ViewInAppNotificationPage)">
<a (click)="readAllNotifications()">{{'NAV-BAR.READ-ALL-INAPP-NOTIFICATIONS'
| translate}}</a> | translate}}</a>
</mat-list-item> </mat-list-item>
</mat-nav-list> </mat-nav-list>

View File

@ -8,4 +8,8 @@
.secondary-text { .secondary-text {
color: rgba(0, 0, 0, 0.54); color: rgba(0, 0, 0, 0.54);
} }
.mat-list-item-content {
text-align: center
}
} }

View File

@ -85,4 +85,12 @@ export class InAppNotificationListingDialogComponent extends BaseComponent imple
this.router.navigate(['/inapp-notifications']); this.router.navigate(['/inapp-notifications']);
this.dialogRef.close(); this.dialogRef.close();
} }
readAllNotifications() {
this.inappNotificationService.readAll()
.pipe(takeUntil(this._destroyed))
.subscribe(
data => {},
);
}
} }

View File

@ -22,7 +22,7 @@
</mat-form-field> </mat-form-field>
<div class="col-md-3 d-flex justify-content-center align-items-center"> <div class="col-md-3 d-flex justify-content-center align-items-center">
<mat-slide-toggle [(ngModel)]="isActive" class="toggle col-auto w-100"> <mat-slide-toggle [(ngModel)]="isActive" class="toggle col-auto w-100">
{{'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FILTER.SHOW-INACTIVE' | translate}} {{'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FILTER.IS-ACTIVE' | translate}}
</mat-slide-toggle> </mat-slide-toggle>
</div> </div>
</div> </div>

View File

@ -60,7 +60,14 @@ export class InAppNotificationListingFiltersComponent extends BaseComponent impl
return this.filter.trackingState ? this.filter.trackingState : null; return this.filter.trackingState ? this.filter.trackingState : null;
} }
set trackingState(value: NotificationInAppTracking[]) { set trackingState(value: NotificationInAppTracking[]) {
this.filter.trackingState = value && value.length > 0 ? value : null; // 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); this.filterChange.emit(this.filter);
} }
} }

View File

@ -78,16 +78,16 @@ export class InAppNotificationListingComponent extends BaseListingComponent<InAp
}, { }, {
prop: nameof<InAppNotification>(x => x.subject), prop: nameof<InAppNotification>(x => x.subject),
sortable: true, sortable: true,
languageName: 'INAPP-NOTIFICATION-LISTING.FIELDS.SUBJECT' languageName: 'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FIELDS.SUBJECT'
}, { }, {
prop: nameof<InAppNotification>(x => x.trackingState), prop: nameof<InAppNotification>(x => x.trackingState),
sortable: true, sortable: true,
languageName: 'INAPP-NOTIFICATION-LISTING.FIELDS.TRACKING-STATE', languageName: 'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FIELDS.TRACKING-STATE',
pipe: this.pipeService.getPipe<NotificationInAppTrackingTypePipe>(NotificationInAppTrackingTypePipe) pipe: this.pipeService.getPipe<NotificationInAppTrackingTypePipe>(NotificationInAppTrackingTypePipe)
}, { }, {
prop: nameof<InAppNotification>(x => x.createdAt), prop: nameof<InAppNotification>(x => x.createdAt),
sortable: true, sortable: true,
languageName: 'INAPP-NOTIFICATION-LISTING.FIELDS.CREATED-AT', languageName: 'NOTIFICATION-SERVICE.INAPP-NOTIFICATION-LISTING.FIELDS.CREATED-AT',
pipe: this.pipeService.getPipe<DataTableDateTimeFormatPipe>(DataTableDateTimeFormatPipe).withFormat('short') pipe: this.pipeService.getPipe<DataTableDateTimeFormatPipe>(DataTableDateTimeFormatPipe).withFormat('short')
}]); }]);
} }
@ -105,6 +105,7 @@ export class InAppNotificationListingComponent extends BaseListingComponent<InAp
} }
protected loadListing() : Observable<QueryResult<InAppNotification>> { protected loadListing() : Observable<QueryResult<InAppNotification>> {
console.log(this.lookup);
return this.inappNotificationService.query(this.lookup); return this.inappNotificationService.query(this.lookup);
} }

View File

@ -32,6 +32,11 @@
<app-language (languageChange)="getLanguage($event)"></app-language> <app-language (languageChange)="getLanguage($event)"></app-language>
</mat-menu> </mat-menu>
</div> </div>
<div class="col-auto" *ngIf="isAuthenticated() && authentication.hasPermission(authentication.permissionEnum.ViewInAppNotificationPage)">
<button class="col-auto" mat-icon-button matTooltip="{{'NAV-BAR.INAPP-NOTIFICATIONS' | translate}}" (click)="toggleInAppNotifications()">
<mat-icon [matBadge]="inAppNotificationCount" [matBadgeHidden]="inAppNotificationCount <= 0" matBadgeColor="warn">mail</mat-icon>
</button>
</div>
<!-- <app-search></app-search> --> <!-- <app-search></app-search> -->

View File

@ -1,6 +1,6 @@
import { Location } from '@angular/common'; import { Location } from '@angular/common';
import { Component, ElementRef, EventEmitter, OnInit, Output, ViewChild } from '@angular/core'; import { Component, ElementRef, EventEmitter, OnInit, Output, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { MatMenuTrigger } from '@angular/material/menu'; import { MatMenuTrigger } from '@angular/material/menu';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { AppRole } from '@app/core/common/enum/app-role'; import { AppRole } from '@app/core/common/enum/app-role';
@ -16,6 +16,10 @@ import { StartNewDmpDialogComponent } from '../dmp/new/start-new-dmp-dialogue/st
import { FaqDialogComponent } from '../faq/dialog/faq-dialog.component'; import { FaqDialogComponent } from '../faq/dialog/faq-dialog.component';
import { UserDialogComponent } from './user-dialog/user-dialog.component'; import { UserDialogComponent } from './user-dialog/user-dialog.component';
import { DATASETS_ROUTES, DMP_ROUTES, GENERAL_ROUTES } from '../sidebar/sidebar.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 { InAppNotificationService } from '@app/core/services/inapp-notification/inapp-notification.service';
import { timer } from 'rxjs';
import { ConfigurationService } from '@app/core/services/configuration/configuration.service';
@Component({ @Component({
selector: 'app-navbar', selector: 'app-navbar',
@ -33,18 +37,22 @@ export class NavbarComponent extends BaseComponent implements OnInit {
currentRoute: string; currentRoute: string;
selectedLanguage: string; selectedLanguage: string;
private user: User; private user: User;
inAppNotificationDialog: MatDialogRef<InAppNotificationListingDialogComponent> = null;
inAppNotificationCount = 0;
@Output() sidebarToggled: EventEmitter<any> = new EventEmitter(); @Output() sidebarToggled: EventEmitter<any> = new EventEmitter();
@ViewChild(MatMenuTrigger) trigger: MatMenuTrigger; @ViewChild(MatMenuTrigger) trigger: MatMenuTrigger;
constructor(location: Location, constructor(location: Location,
private element: ElementRef, private element: ElementRef,
private router: Router, private router: Router,
private authentication: AuthService, public authentication: AuthService,
private dialog: MatDialog, private dialog: MatDialog,
private progressIndicationService: ProgressIndicationService, private progressIndicationService: ProgressIndicationService,
private languageService: LanguageService, private languageService: LanguageService,
private matomoService: MatomoService, private matomoService: MatomoService,
private sidenavService: SideNavService, private sidenavService: SideNavService,
private inappNotificationService: InAppNotificationService,
private configurationService: ConfigurationService
) { ) {
super(); super();
this.location = location; this.location = location;
@ -75,6 +83,23 @@ export class NavbarComponent extends BaseComponent implements OnInit {
this.progressIndicationService.getProgressIndicationObservable().pipe(takeUntil(this._destroyed)).subscribe(x => { this.progressIndicationService.getProgressIndicationObservable().pipe(takeUntil(this._destroyed)).subscribe(x => {
setTimeout(() => { this.progressIndication = x; }); setTimeout(() => { this.progressIndication = x; });
}); });
timer(2000, this.configurationService.inAppNotificationsCountInterval * 1000)
.pipe(takeUntil(this._destroyed))
.subscribe(x => {
this.countUnreadInappNotifications();
});
}
private countUnreadInappNotifications() {
if (this.isAuthenticated()) {
this.inappNotificationService.countUnread()
.pipe(takeUntil(this._destroyed))
.subscribe(
data => {
this.inAppNotificationCount = data;
},
);
}
} }
public isAuthenticated(): boolean { public isAuthenticated(): boolean {
@ -273,4 +298,21 @@ export class NavbarComponent extends BaseComponent implements OnInit {
this.router.navigate(['/logout']); this.router.navigate(['/logout']);
} }
toggleInAppNotifications() {
if (this.inAppNotificationDialog != null) {
this.inAppNotificationDialog.close();
} else {
this.countUnreadInappNotifications();
this.inAppNotificationDialog = this.dialog.open(InAppNotificationListingDialogComponent, {
position: {
top: '64px', right: '0px'
}
});
this.inAppNotificationDialog.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => {
this.countUnreadInappNotifications();
this.inAppNotificationDialog = null;
});
}
}
} }

View File

@ -19,6 +19,7 @@
"clientSecret": null, "clientSecret": null,
"grantType": "code" "grantType": "code"
}, },
"inAppNotificationsCountInterval": "30",
"notification_service": { "notification_service": {
"enabled": true, "enabled": true,
"address": "http://localhost:8086/api/" "address": "http://localhost:8086/api/"

View File

@ -314,7 +314,9 @@
"DMP": "DMP", "DMP": "DMP",
"GRANT": "Grant", "GRANT": "Grant",
"PUBLISHED": "Published" "PUBLISHED": "Published"
} },
"INAPP-NOTIFICATIONS": "All Notifications",
"READ-ALL-INAPP-NOTIFICATIONS": "Read All"
}, },
"SIDE-BAR": { "SIDE-BAR": {
"GENERAL": "GENERAL", "GENERAL": "GENERAL",
@ -1328,6 +1330,43 @@
} }
}, },
"NOTIFICATION-SERVICE": { "NOTIFICATION-SERVICE": {
"INAPP-NOTIFICATION-LISTING": {
"FIELDS": {
"SUBJECT": "Subject",
"TRACKING-STATE": "Tracking State",
"CREATED-AT": "Created",
"IS-ACTIVE": "Is Active"
},
"FILTER": {
"MORE-FILTERS": "More filters",
"TRACKING-STATE":"Tracking State",
"IS-ACTIVE": "Is Active",
"CHANNEL": "Channel",
"CANCEL": "Cancel",
"APPLY-FILTERS": "Apply filters"
},
"CONFIRM-DELETE-DIALOG": {
"MESSAGE": "Would you like to delete this Notification Template?",
"CONFIRM-BUTTON": "Yes, delete",
"CANCEL-BUTTON": "No"
},
"ACTIONS": {
"DELETE": "Delete",
"EDIT": "Edit"
},
"SUCCESSFUL-DELETE": "Successful Delete",
"UNSUCCESSFUL-DELETE": "This item could not be deleted."
},
"INAPP-NOTIFICATION-EDITOR": {
"FIELDS": {
},
"ACTIONS": {
"READ": "Read",
"CANCEL": "Cancel",
"DELETE": "Delete"
}
},
"NOTIFICATION-TEMPLATE-EDITOR": { "NOTIFICATION-TEMPLATE-EDITOR": {
"NEW": "New Notification Template", "NEW": "New Notification Template",
"FIELDS": { "FIELDS": {
@ -2275,6 +2314,10 @@
"DESCRIPTION-TEMPLATE-INVITATION": "Description Template Invitation", "DESCRIPTION-TEMPLATE-INVITATION": "Description Template Invitation",
"CONTACT-SUPPORT": "Contact Support", "CONTACT-SUPPORT": "Contact Support",
"PUBLIC-CONTACT-SUPPORT": "Public Contact Support" "PUBLIC-CONTACT-SUPPORT": "Public Contact Support"
},
"NOTIFICATION-INAPP-TRACKING": {
"STORED": "Stored",
"DELIVERED": "Delivered"
} }
}, },
"ADDRESEARCHERS-EDITOR": { "ADDRESEARCHERS-EDITOR": {