1. Add notifications in user-mini in mobile

This commit is contained in:
Konstantinos Triantafyllou 2023-03-24 17:13:33 +02:00
parent 31d52de0e8
commit a9f31d8307
7 changed files with 179 additions and 110 deletions

View File

@ -1,10 +1,16 @@
import {Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges} from '@angular/core';
import {Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {Session, User} from './utils/helper.class';
import {RouterHelper} from '../utils/routerHelper.class';
import {Subscriber} from "rxjs";
import {MenuItem} from "../sharedComponents/menu";
import {UserManagementService} from "../services/user-management.service";
import {
NotificationConfiguration,
NotificationsSidebarComponent
} from "../notifications/notifications-sidebar/notifications-sidebar.component";
declare var UIkit;
@Component({
selector: 'user-mini',
@ -41,42 +47,67 @@ import {UserManagementService} from "../services/user-management.service";
<icon name="login" ratio="1.5" [flex]="true"></icon>
</a>
<a *ngIf="loggedIn && mobileView" href="#account" class="login uk-icon" uk-toggle>
<svg height="30" width="30">
<circle cx="15" cy="15" r="15" stroke-width="2"></circle>
<text x="50%" y="50%" text-anchor="middle" dy=".35em" font-size="14">
{{firstLetters ? firstLetters : 'AN'}}
</text>
</svg>
<span class="uk-position-relative">
<svg height="30" width="30">
<circle cx="15" cy="15" r="15" stroke-width="2"></circle>
<text x="50%" y="50%" text-anchor="middle" dy=".35em" font-size="14">
{{firstLetters ? firstLetters : 'AN'}}
</text>
</svg>
<span *ngIf="notificationsSidebar && notificationsSidebar.unreadCount > 0" class="uk-text-secondary notification">
<icon name="circle" ratio="0.8"></icon>
</span>
</span>
</a>
<div *ngIf="loggedIn" id="account" class="uk-offcanvas" uk-offcanvas="flip: true; overlay: true">
<div class="uk-offcanvas-bar uk-padding-remove-horizontal">
<button class="uk-offcanvas-close uk-icon uk-close">
<icon name="close" ratio="1.5" visuallyHidden="close menu"></icon>
</button>
<div class="uk-padding uk-flex uk-flex-middle">
<div class="login">
<svg height="60" width="60" style="max-width: 60px; height: 60px;">
<circle cx="30" cy="30" r="20" stroke-width="2"></circle>
<text x="50%" y="50%" text-anchor="middle" dy=".4em" font-size="16">
{{firstLetters ? firstLetters : 'AN'}}
</text>
</svg>
<div *ngIf="loggedIn" #account id="account" class="uk-offcanvas" uk-offcanvas="flip: true; overlay: true;">
<div class="uk-offcanvas-bar uk-padding-remove">
<nav class="uk-navbar uk-background-default" uk-sticky>
<div class="uk-navbar-right">
<button class="uk-navbar-toggle uk-icon uk-close" (click)="closeCanvas(account)">
<icon name="close" ratio="1.5" visuallyHidden="close account"></icon>
</button>
</div>
<h5 class="uk-margin-small-left uk-margin-remove-bottom uk-margin-remove-top uk-text-truncate">
{{user.fullname}}
</h5>
</div>
<ul class="uk-nav uk-nav-primary uk-list uk-margin-top uk-nav-parent-icon" uk-nav>
<ng-container *ngFor="let item of userMenuItems ">
<li *ngIf="item.needsAuthorization && isAuthorized || !item.needsAuthorization">
<a *ngIf="item.route" [routerLink]="item.route" (click)="closeCanvas()">{{item.title}}</a>
<a *ngIf="!item.route && item.url" (click)="closeCanvas()" [href]="item.url" [class.custom-external]="item.target != '_self'"
[target]="item.target">{{item.title}}</a>
</li>
</ng-container>
<li *ngIf="userMenuItems.length > 0" class="uk-nav-divider"></li>
<li><a (click)="logOut()">Log out</a></li>
</ul>
</nav>
<ng-container *ngIf="!showNotifications">
<div class="uk-padding uk-padding-remove-top uk-flex uk-flex-middle">
<div class="login">
<svg height="60" width="60" style="max-width: 60px; height: 60px;">
<circle cx="30" cy="30" r="20" stroke-width="2"></circle>
<text x="50%" y="50%" text-anchor="middle" dy=".4em" font-size="16">
{{firstLetters ? firstLetters : 'AN'}}
</text>
</svg>
</div>
<h5 class="uk-margin-small-left uk-margin-remove-bottom uk-margin-remove-top uk-text-truncate">
{{user.fullname}}
</h5>
</div>
<ul class="uk-nav uk-nav-primary uk-list uk-margin-top uk-nav-parent-icon" uk-nav>
<ng-container *ngFor="let item of userMenuItems ">
<li *ngIf="item.needsAuthorization && isAuthorized || !item.needsAuthorization">
<a *ngIf="item.route" [routerLink]="item.route" (click)="closeCanvas(account)">{{item.title}}</a>
<a *ngIf="!item.route && item.url" (click)="closeCanvas(account)" [href]="item.url" [class.custom-external]="item.target != '_self'"
[target]="item.target">{{item.title}}</a>
</li>
</ng-container>
<ng-container *ngIf="notificationConfiguration">
<li *ngIf="userMenuItems.length > 0" class="uk-nav-divider"></li>
<li *ngIf="notificationConfiguration">
<a (click)="toggleNotifications()">
<div class="uk-flex uk-flex-middle uk-width-1-1">
<span class="uk-width-expand">Notifications</span>
<icon *ngIf="notificationsSidebar?.unreadCount > 0" class="uk-margin-small-left uk-text-secondary uk-margin-right" name="circle" [flex]="true" ratio="0.8"></icon>
</div>
</a>
</li>
</ng-container>
<li *ngIf="userMenuItems.length > 0" class="uk-nav-divider"></li>
<li><a (click)="logOut()">Log out</a></li>
</ul>
</ng-container>
<notification-sidebar [class.uk-hidden]="!showNotifications" #notificationsSidebar *ngIf="notificationConfiguration" [mobile]="true"
(showNotificationsEmitter)="showNotifications = $event"
[configuration]="notificationConfiguration" [user]="user"></notification-sidebar>
</div>
</div>
</li>
@ -95,7 +126,9 @@ export class UserMiniComponent implements OnInit, OnChanges {
@Input() logInUrl;
@Input() logOutUrl;
@Input() cookieDomain;
@Output() closeCanvasEmitter: EventEmitter<boolean> = new EventEmitter<boolean>();
@Input() notificationConfiguration: NotificationConfiguration;
@ViewChild('notificationsSidebar') notificationsSidebar: NotificationsSidebarComponent;
public showNotifications = false;
private subscriptions = [];
constructor(private router: Router, private route: ActivatedRoute, private userManagementService: UserManagementService) {
@ -122,8 +155,8 @@ export class UserMiniComponent implements OnInit, OnChanges {
});
}
closeCanvas() {
this.closeCanvasEmitter.emit(true);
closeCanvas(canvas) {
UIkit.offcanvas(canvas).hide();
}
initUser() {
@ -166,4 +199,8 @@ export class UserMiniComponent implements OnInit, OnChanges {
this.firstLetters += matches.join('');
}
}
toggleNotifications() {
this.showNotifications = !this.showNotifications;
}
}

View File

@ -7,10 +7,11 @@ import {UserMiniComponent} from "./userMini.component";
import {IconsModule} from "../utils/icons/icons.module";
import {IconsService} from "../utils/icons/icons.service";
import {login} from "../utils/icons/icons";
import {NotificationsSidebarModule} from "../notifications/notifications-sidebar/notifications-sidebar.module";
@NgModule({
imports: [
CommonModule, FormsModule, RouterModule, IconsModule
CommonModule, FormsModule, RouterModule, IconsModule, NotificationsSidebarModule
],
declarations: [
UserMiniComponent

View File

@ -5,7 +5,7 @@
}
#notifications .notification-list {
padding: @global-medium-gutter 0 @global-medium-gutter @global-medium-gutter;
padding: 0 @global-medium-gutter;
}
#notifications .notification-list:not(:last-child) {
@ -29,6 +29,6 @@
}
#notifications .notification {
padding: @global-medium-gutter @global-medium-gutter;
padding: 0 @global-medium-gutter @global-medium-gutter @global-medium-gutter;
overflow: auto;
}

View File

@ -1,4 +1,14 @@
import {Component, Input, OnDestroy, OnInit, ViewEncapsulation} from "@angular/core";
import {
Component,
ElementRef,
EventEmitter,
Input,
OnDestroy,
OnInit,
Output,
ViewChild,
ViewEncapsulation
} from "@angular/core";
import {Notification} from "../notifications";
import {NotificationService} from "../notification.service";
import {Subscription} from "rxjs";
@ -8,71 +18,92 @@ import {Option} from "../../sharedComponents/input/input.component";
declare var UIkit;
export class NotificationConfiguration {
availableGroups: Option[] = [];
entities: string[] = [];
service: string;
}
@Component({
selector: 'notification-sidebar',
template: `
<div id="notifications-switcher" uk-toggle="" href="#notifications" class="uk-offcanvas-switcher uk-flex uk-flex-middle uk-flex-center">
<div *ngIf="!mobile" id="notifications-switcher" uk-toggle="" href="#notifications" class="uk-offcanvas-switcher uk-flex uk-flex-middle uk-flex-center">
<icon name="mail" ratio="1.5" customClass="uk-text-background" flex="true" visuallyHidden="Notifications"></icon>
<span [class.uk-hidden]="unreadCount === 0" class="uk-offcanvas-count uk-flex uk-flex-middle uk-flex-center">
{{unreadCount}}
</span>
</div>
<div id="notifications" class="uk-offcanvas" uk-offcanvas="flip: true; overlay: true;">
<div class="uk-offcanvas-bar uk-padding-remove">
<button class="uk-offcanvas-close uk-close uk-icon" type="button">
<icon name="close" ratio="1.5" visuallyHidden="close"></icon>
</button>
<ng-template [ngIf]="!notification">
<div class="notification-list uk-position-relative">
<h4>Notifications</h4>
<div class="uk-flex uk-flex-right@m uk-flex-center uk-padding uk-padding-remove-vertical">
<button [disabled]="unreadCount === 0" (click)="readAll()" class="uk-button uk-button-link">Mark As Read ({{unreadCount}})</button>
</div>
<h6 *ngIf="notifications.length == 0" class="uk-position-center uk-margin-remove">No notifications</h6>
<ul *ngIf="notifications.length > 0" class="uk-list">
<li *ngFor="let notification of notifications; let i=index" class="clickable" (click)="select(notification)">
<div class="uk-grid uk-grid-small" uk-grid>
<notification-user [name]="notification.name" [surname]="notification.surname" [outline]="true"
colorClass="uk-text-secondary"></notification-user>
<div class="uk-width-expand">
<div class="uk-width-1-1 uk-flex uk-flex-middle">
<div class="uk-width-expand multi-line-ellipsis lines-2">
<p class="uk-margin-remove" [class.uk-text-light-grey]="notification.read">
{{notification.preview}}
</p>
</div>
<div class="uk-margin-left uk-flex uk-flex-center uk-text-secondary">
<icon *ngIf="!notification.read" name="circle" ratio="0.6" visuallyHidden="unread"></icon>
</div>
</div>
<span class="uk-text-secondary uk-text-small">{{getDate(notification.date)}}</span>
</div>
</div>
</li>
</ul>
</div>
<div *ngIf="availableGroups.length > 0" [availableGroups]="availableGroups" [entities]="entities" [service]="service" notify-form class="notify"></div>
</ng-template>
<div *ngIf="notification" class="notification">
<div class="uk-flex uk-flex-middle uk-margin-medium-bottom">
<span class="uk-text-secondary clickable" (click)="back($event)">
<icon ratio="1.5" name="west" visuallyHidden="back"></icon>
<ng-template #main>
<ng-container *ngIf="!notification">
<div class="notification-list uk-position-relative">
<h4 class="uk-flex uk-flex-middle clickable uk-margin-remove-top uk-margin-medium-bottom" (click)="showNotificationsEmitter.emit(false)">
<span *ngIf="mobile" class="uk-margin-right">
<icon ratio="1.5" name="west" visuallyHidden="back" [flex]="true"></icon>
</span>
<h4 *ngIf="notification.title" class="uk-text-bold uk-margin-left">{{notification.title}}</h4>
<div class="uk-text-bold">Notifications</div>
</h4>
<div class="uk-flex uk-flex-right@m uk-flex-center uk-padding uk-padding-remove-vertical">
<button [disabled]="unreadCount === 0" (click)="readAll()" class="uk-button uk-button-link">Mark As Read ({{unreadCount}})</button>
</div>
<div class="uk-flex uk-flex-middle uk-margin-medium-bottom">
<notification-user [name]="notification.name" [surname]="notification.surname" colorClass="uk-text-secondary" [outline]="true"></notification-user>
<div class="uk-margin-left">
{{notification.name + ' ' + notification.surname}}<br>
<span style="opacity: 0.8;" class="uk-text-small uk-margin-small-top">
<h6 *ngIf="notifications.length == 0" class="uk-position-center uk-margin-remove">No notifications</h6>
<ul *ngIf="notifications.length > 0" class="uk-list">
<li *ngFor="let notification of notifications; let i=index" class="clickable" (click)="select(notification)">
<div class="uk-grid uk-grid-small" uk-grid>
<notification-user [name]="notification.name" [surname]="notification.surname" [outline]="true"
colorClass="uk-text-secondary"></notification-user>
<div class="uk-width-expand">
<div class="uk-width-1-1 uk-flex uk-flex-middle">
<div class="uk-width-expand multi-line-ellipsis lines-2">
<p class="uk-margin-remove" [class.uk-text-light-grey]="notification.read">
{{notification.preview}}
</p>
</div>
<div class="uk-margin-left uk-flex uk-flex-center uk-text-secondary">
<icon *ngIf="!notification.read" name="circle" ratio="0.6" visuallyHidden="unread"></icon>
</div>
</div>
<span class="uk-text-secondary uk-text-small">{{getDate(notification.date)}}</span>
</div>
</div>
</li>
</ul>
</div>
<div *ngIf="configuration.availableGroups.length > 0" [availableGroups]="configuration.availableGroups" [entities]="configuration.entities" [service]="configuration.service" notify-form class="notify"></div>
</ng-container>
<div *ngIf="notification" class="notification">
<h4 class="uk-flex uk-flex-middle clickable uk-margin-remove-top uk-margin-medium-bottom" (click)="back($event)">
<span class="uk-margin-right">
<icon ratio="1.5" name="west" visuallyHidden="back" [flex]="true"></icon>
</span>
<div *ngIf="notification.title" class="uk-text-bold">{{notification.title}}</div>
</h4>
<div class="uk-flex uk-flex-middle uk-margin-medium-bottom">
<notification-user [name]="notification.name" [surname]="notification.surname" colorClass="uk-text-secondary" [outline]="true"></notification-user>
<div class="uk-margin-left">
{{notification.name + ' ' + notification.surname}}<br>
<span style="opacity: 0.8;" class="uk-text-small uk-margin-small-top">
{{notification.date | date:'medium'}} ({{getDate(notification.date)}})
</span>
</div>
</div>
<div [innerHTML]="notification.message | safeHtml">
</div>
</div>
<div [innerHTML]="notification.message | safeHtml">
</div>
</div>
</ng-template>
<div *ngIf="!mobile" #canvas id="notifications" class="uk-offcanvas" uk-offcanvas="flip: true; overlay: true;">
<div class="uk-offcanvas-bar uk-padding-remove">
<nav class="uk-navbar uk-background-default" uk-sticky>
<div class="uk-navbar-right">
<button class="uk-navbar-toggle uk-icon uk-close" (click)="closeCanvas(canvas)">
<icon name="close" ratio="1.5" visuallyHidden="close account"></icon>
</button>
</div>
</nav>
<ng-container *ngTemplateOutlet="main"></ng-container>
</div>
</div>
<div *ngIf="mobile" id="notifications">
<ng-container *ngTemplateOutlet="main"></ng-container>
</div>
`,
styleUrls: ['notification-sidebar.component.less'],
@ -81,21 +112,21 @@ declare var UIkit;
export class NotificationsSidebarComponent implements OnInit, OnDestroy {
@Input()
public user: User;
@Input()
public mobile: boolean = false;
@Input()
public configuration: NotificationConfiguration;
@Output()
public showNotificationsEmitter: EventEmitter<boolean> = new EventEmitter<boolean>();
public notifications: Notification[] = [];
@Input()
public availableGroups: Option[] = [];
@Input()
public entities: string[] = [];
@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.subscriptions.push(this.notificationService.getNotifications(this.configuration.service).subscribe(notifications => {
this.notifications = notifications;
}, error => {
this.notifications = [];
@ -141,8 +172,12 @@ export class NotificationsSidebarComponent implements OnInit, OnDestroy {
this.notification = null;
}
closeCanvas(canvas) {
UIkit.offcanvas(canvas).hide();
}
readAll() {
this.notificationService.markAllAsRead(this.service).subscribe(() => {
this.notificationService.markAllAsRead(this.configuration.service).subscribe(() => {
this.notifications.forEach(notification => {
notification.read = true;
});

View File

@ -12,8 +12,8 @@
</div>
<div *ngIf="!onlyTop || userMenu" class="uk-navbar-right" [class.uk-light]='activeHeader.darkBg'>
<ng-container *ngIf="userMenu">
<user-mini [user]="user" mobileView=true (closeCanvasEmitter)="closeCanvas(canvas)"
[userMenuItems]=userMenuItems [logInUrl]=properties.loginUrl
<user-mini [user]="user" mobileView=true
[userMenuItems]=userMenuItems [logInUrl]=properties.loginUrl [notificationConfiguration]="notificationConfiguration"
[logOutUrl]=properties.logoutUrl [cookieDomain]=properties.cookieDomain></user-mini>
</ng-container>
</div>

View File

@ -8,6 +8,7 @@ import {Subscription} from 'rxjs';
import {HelpContentService} from '../services/help-content.service';
import {properties} from "../../../environments/environment";
import {LayoutService} from "../dashboard/sharedComponents/sidebar/layout.service";
import {NotificationConfiguration} from "../notifications/notifications-sidebar/notifications-sidebar.component";
declare var UIkit;
@ -48,6 +49,7 @@ export class NavigationBarComponent implements OnInit, OnDestroy, OnChanges {
@Input() searchRoute: string = '/search/find';
@Input() searchPlaceHolder: string = 'Search for research results';
@Input() showLogo: boolean = true;
@Input() notificationConfiguration: NotificationConfiguration;
replaceHeader: boolean = false;
public activeHeader: Header;
keyword: string = '';

View File

@ -4,16 +4,10 @@ import {FullPageSliderComponent} from "./full-page-slider.component";
import {SlideComponent} from "./slide.component";
import {BottomModule} from '../../sharedComponents/bottom.module';
import {IconsModule} from '../icons/icons.module';
import {IconsService} from '../icons/icons.service';
import {arrow_down, arrow_up} from '../icons/icons';
@NgModule({
imports: [CommonModule, BottomModule, IconsModule],
declarations: [FullPageSliderComponent, SlideComponent],
exports: [FullPageSliderComponent, SlideComponent],
})
export class FullPageSliderModule {
constructor(private iconsService: IconsService) {
this.iconsService.registerIcons([arrow_up, arrow_down]);
}
}
export class FullPageSliderModule {}