You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by bo...@apache.org on 2023/01/12 20:47:49 UTC

[streampipes] 02/02: [#877] apply formatting and linting to notifications module

This is an automated email from the ASF dual-hosted git repository.

bossenti pushed a commit to branch chore/formatting-lintin-ns-module
in repository https://gitbox.apache.org/repos/asf/streampipes.git

commit 204eecc4cb29ace8c44e5a03f3e341359333c203
Author: bossenti <bo...@posteo.de>
AuthorDate: Thu Jan 12 21:47:23 2023 +0100

    [#877] apply formatting and linting to notifications module
---
 ui/.eslintignore                                   |   1 -
 ui/.prettierignore                                 |   1 -
 .../components/notification-item.component.html    |   5 +-
 .../components/notification-item.component.scss    |   2 +-
 .../components/notification-item.component.ts      |  13 +-
 .../app/notifications/notifications.component.html | 109 +++--
 .../app/notifications/notifications.component.scss |  15 +-
 .../app/notifications/notifications.component.ts   | 451 ++++++++++++---------
 ui/src/app/notifications/notifications.module.ts   |  21 +-
 .../notifications/service/notifications.service.ts |  76 ++--
 .../app/notifications/utils/notifications.utils.ts |  10 +-
 11 files changed, 427 insertions(+), 277 deletions(-)

diff --git a/ui/.eslintignore b/ui/.eslintignore
index aaf2800bf..df54ff075 100644
--- a/ui/.eslintignore
+++ b/ui/.eslintignore
@@ -31,4 +31,3 @@ src/app/editor
 src/app/files
 src/app/info
 src/app/login
-src/app/notifications
diff --git a/ui/.prettierignore b/ui/.prettierignore
index 384124140..4b0f32f39 100644
--- a/ui/.prettierignore
+++ b/ui/.prettierignore
@@ -31,4 +31,3 @@ src/app/editor
 src/app/files
 src/app/info
 src/app/login
-src/app/notifications
diff --git a/ui/src/app/notifications/components/notification-item.component.html b/ui/src/app/notifications/components/notification-item.component.html
index 1f8786d94..6b7cbc151 100644
--- a/ui/src/app/notifications/components/notification-item.component.html
+++ b/ui/src/app/notifications/components/notification-item.component.html
@@ -18,11 +18,12 @@
 <div class="notification-item">
     <div class="i">
         <div class="head">
-            <span class="time">{{notification.createdAt | date: 'yyyy-MM-dd HH:mm:ss'}}</span>
+            <span class="time">{{
+                notification.createdAt | date : 'yyyy-MM-dd HH:mm:ss'
+            }}</span>
         </div>
         <div class="notification-box sp-accent-bg">
             <div [innerHTML]="sanitizedMessage"></div>
         </div>
     </div>
-
 </div>
diff --git a/ui/src/app/notifications/components/notification-item.component.scss b/ui/src/app/notifications/components/notification-item.component.scss
index bbb3b9270..b74594c20 100644
--- a/ui/src/app/notifications/components/notification-item.component.scss
+++ b/ui/src/app/notifications/components/notification-item.component.scss
@@ -52,4 +52,4 @@
 
 .notification-item {
     margin-top: 30px;
-}
\ No newline at end of file
+}
diff --git a/ui/src/app/notifications/components/notification-item.component.ts b/ui/src/app/notifications/components/notification-item.component.ts
index b363383bf..5cf6d949a 100644
--- a/ui/src/app/notifications/components/notification-item.component.ts
+++ b/ui/src/app/notifications/components/notification-item.component.ts
@@ -20,20 +20,19 @@ import { NotificationItem } from '../model/notifications.model';
 import { DomSanitizer } from '@angular/platform-browser';
 
 @Component({
-    selector: 'notification-item',
+    selector: 'sp-notification-item',
     templateUrl: './notification-item.component.html',
-    styleUrls: ['./notification-item.component.scss']
+    styleUrls: ['./notification-item.component.scss'],
 })
 export class NotificationItemComponent implements OnInit {
-
     @Input() notification: NotificationItem;
     sanitizedMessage;
 
-    constructor(private domSanitizer: DomSanitizer) {
-
-    }
+    constructor(private domSanitizer: DomSanitizer) {}
 
     ngOnInit(): void {
-        this.sanitizedMessage = this.domSanitizer.bypassSecurityTrustHtml(this.notification.message);
+        this.sanitizedMessage = this.domSanitizer.bypassSecurityTrustHtml(
+            this.notification.message,
+        );
     }
 }
diff --git a/ui/src/app/notifications/notifications.component.html b/ui/src/app/notifications/notifications.component.html
index e91ac5945..cafa23a3e 100644
--- a/ui/src/app/notifications/notifications.component.html
+++ b/ui/src/app/notifications/notifications.component.html
@@ -17,7 +17,7 @@
   -->
 
 <div fxLayout="column" class="page-container page-container-max-height">
-    <div fxLayout="row" style="padding:0px;" class="sp-tab-bg">
+    <div fxLayout="row" style="padding: 0px" class="sp-tab-bg">
         <div fxFlex="100" class="page-container-nav">
             <div fxFlex="100" fxLayout="row">
                 <div fxFlex fxLayoutAlign="start center">
@@ -25,51 +25,108 @@
                         <mat-tab label="My Notifications"></mat-tab>
                     </mat-tab-group>
                 </div>
-                <div fxFlex fxLayoutAlign="end center" class="mr-20">
-
-                </div>
+                <div fxFlex fxLayoutAlign="end center" class="mr-20"></div>
             </div>
         </div>
     </div>
-    <div class="container-fluid marketplace-container" *ngIf="notificationsLoading" fxFlex="100" fxLayoutAlign="center center" fxLayout="column">
+    <div
+        class="container-fluid marketplace-container"
+        *ngIf="notificationsLoading"
+        fxFlex="100"
+        fxLayoutAlign="center center"
+        fxLayout="column"
+    >
         <mat-spinner [mode]="'indeterminate'" [diameter]="20"></mat-spinner>
         <h4>Loading notifications...</h4>
     </div>
-    <div class="fixed-height page-container-padding-inner" *ngIf="!notificationsLoading && !pipelinesWithNotificationsPresent" fxFlex="100" fxLayoutAlign="center center" fxLayout="row">
-        <h4>No notifications available. Create a new pipeline using the Notification Sink to create your first notification!</h4>
+    <div
+        class="fixed-height page-container-padding-inner"
+        *ngIf="!notificationsLoading && !pipelinesWithNotificationsPresent"
+        fxFlex="100"
+        fxLayoutAlign="center center"
+        fxLayout="row"
+    >
+        <h4>
+            No notifications available. Create a new pipeline using the
+            Notification Sink to create your first notification!
+        </h4>
     </div>
-    <div class="fixed-height page-container-padding-inner" fxLayout="row" fxFlex="100" *ngIf="!notificationsLoading && pipelinesWithNotificationsPresent">
+    <div
+        class="fixed-height page-container-padding-inner"
+        fxLayout="row"
+        fxFlex="100"
+        *ngIf="!notificationsLoading && pipelinesWithNotificationsPresent"
+    >
         <div fxFlex="30" class="notifications-overview scrolling-auto">
             <mat-list>
-                <mat-list-item *ngFor="let existingNotification of existingNotifications"
-                               (click)="selectNotification(existingNotification)" class="list-item"
-                               [ngClass]="{'selected-notification':
-                               existingNotification.notificationId === currentlySelectedNotificationId}">
-                    <div mat-list-avatar
-                         class="notification-avatar sp-accent-bg">{{elementIconText.getElementIconText(existingNotification.pipelineName)}}
+                <mat-list-item
+                    *ngFor="let existingNotification of existingNotifications"
+                    (click)="selectNotification(existingNotification)"
+                    class="list-item"
+                    [ngClass]="{
+                        'selected-notification':
+                            existingNotification.notificationId ===
+                            currentlySelectedNotificationId
+                    }"
+                >
+                    <div
+                        mat-list-avatar
+                        class="notification-avatar sp-accent-bg"
+                    >
+                        {{
+                            elementIconText.getElementIconText(
+                                existingNotification.pipelineName
+                            )
+                        }}
                     </div>
-                    <h4 mat-line>{{existingNotification.pipelineName}}</h4>
-                    <p mat-line>{{existingNotification.notificationTitle}} </p>
+                    <h4 mat-line>{{ existingNotification.pipelineName }}</h4>
+                    <p mat-line>{{ existingNotification.notificationTitle }}</p>
                     <div class="new-notification-info-panel">
-                        <div class="new-notification-info"
-                             *ngIf="currentlySelectedNotificationId != existingNotification.notificationId &&
-                             newNotificationInfo[existingNotification.notificationId]"></div>
+                        <div
+                            class="new-notification-info"
+                            *ngIf="
+                                currentlySelectedNotificationId !==
+                                    existingNotification.notificationId &&
+                                newNotificationInfo[
+                                    existingNotification.notificationId
+                                ]
+                            "
+                        ></div>
                     </div>
                 </mat-list-item>
             </mat-list>
         </div>
         <div fxFlex="70" class="notifications-details">
             <div class="notification-details-wrapper">
-                <div class="notification-header" fxLayout="column" fxLayoutAlign="center start">
-                    <div class="notification-header-pipeline-name">{{currentlySelectedNotification.pipelineName}}</div>
-                    <div class="notification-header-notification-name">{{currentlySelectedNotification.notificationTitle}}</div>
-                    <hr class="header-divider"/>
+                <div
+                    class="notification-header"
+                    fxLayout="column"
+                    fxLayoutAlign="center start"
+                >
+                    <div class="notification-header-pipeline-name">
+                        {{ currentlySelectedNotification.pipelineName }}
+                    </div>
+                    <div class="notification-header-notification-name">
+                        {{ currentlySelectedNotification.notificationTitle }}
+                    </div>
+                    <hr class="header-divider" />
                 </div>
-                <div #notificationPane class="notification-pane" (scroll)="onScroll()" *ngIf="currentlySelectedNotificationId">
-                    <notification-item [notification]="notification" *ngFor="let notification of allNotifications.get(currentlySelectedNotificationId)"></notification-item>
+                <div
+                    #notificationPane
+                    class="notification-pane"
+                    (scroll)="onScroll()"
+                    *ngIf="currentlySelectedNotificationId"
+                >
+                    <sp-notification-item
+                        [notification]="notification"
+                        *ngFor="
+                            let notification of allNotifications.get(
+                                currentlySelectedNotificationId
+                            )
+                        "
+                    ></sp-notification-item>
                 </div>
             </div>
-
         </div>
     </div>
 </div>
diff --git a/ui/src/app/notifications/notifications.component.scss b/ui/src/app/notifications/notifications.component.scss
index 079936714..4e2ec2c60 100644
--- a/ui/src/app/notifications/notifications.component.scss
+++ b/ui/src/app/notifications/notifications.component.scss
@@ -32,7 +32,7 @@
 }
 
 .mr-20 {
-    margin-right:20px;
+    margin-right: 20px;
 }
 
 .notifications-overview {
@@ -60,11 +60,11 @@
 }
 
 .header-divider {
-    display:flex;
+    display: flex;
     align-self: center;
     margin: 10px 20px;
     width: 100%;
-    border-top: 2px solid $sp-color-accent
+    border-top: 2px solid $sp-color-accent;
 }
 
 .notification-header-pipeline-name {
@@ -83,17 +83,17 @@
 }
 
 .list-item:hover {
-    background: #E0E0E0;
+    background: #e0e0e0;
     cursor: pointer;
 }
 
 .selected-notification {
-    background: #E0E0E0;
+    background: #e0e0e0;
     cursor: pointer;
 }
 
 .list-item {
-    border-bottom: 1px solid #BDBDBD;
+    border-bottom: 1px solid #bdbdbd;
 }
 
 .notification-pane {
@@ -111,7 +111,7 @@
 
 .scrolling-auto {
     overflow: auto;
-    width:100%;
+    width: 100%;
 }
 
 .new-notification-info {
@@ -120,4 +120,3 @@
     height: 10px;
     border-radius: 50%;
 }
-
diff --git a/ui/src/app/notifications/notifications.component.ts b/ui/src/app/notifications/notifications.component.ts
index 4d31082e1..515885c95 100644
--- a/ui/src/app/notifications/notifications.component.ts
+++ b/ui/src/app/notifications/notifications.component.ts
@@ -16,211 +16,294 @@
  *
  */
 
-import { Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core';
-import { ExistingNotification, NotificationItem } from './model/notifications.model';
+import {
+    Component,
+    ElementRef,
+    OnDestroy,
+    OnInit,
+    ViewChild,
+} from '@angular/core';
+import {
+    ExistingNotification,
+    NotificationItem,
+} from './model/notifications.model';
 import { ElementIconText } from '../services/get-element-icon-text.service';
 import { NotificationsService } from './service/notifications.service';
 import { Subscription, timer } from 'rxjs';
 import { NotificationUtils } from './utils/notifications.utils';
 import { NotificationCountService } from '../services/notification-count-service';
-import { FreeTextStaticProperty, Pipeline, PipelineService } from '@streampipes/platform-services';
+import {
+    FreeTextStaticProperty,
+    Pipeline,
+    PipelineService,
+} from '@streampipes/platform-services';
 import { AuthService } from '../services/auth.service';
 import { filter, switchMap } from 'rxjs/operators';
 import { SpBreadcrumbService } from '@streampipes/shared-ui';
 
 @Component({
-  selector: 'notifications',
-  templateUrl: './notifications.component.html',
-  styleUrls: ['./notifications.component.scss']
+    selector: 'sp-notifications',
+    templateUrl: './notifications.component.html',
+    styleUrls: ['./notifications.component.scss'],
 })
 export class NotificationsComponent implements OnInit, OnDestroy {
+    static readonly NOTIFICATIONS_APP_ID =
+        'org.apache.streampipes.sinks.internal.jvm.notification';
+    static readonly NOTIFICATION_TITLE_KEY = 'title';
 
-  static readonly NOTIFICATIONS_APP_ID = 'org.apache.streampipes.sinks.internal.jvm.notification';
-  static readonly NOTIFICATION_TITLE_KEY = 'title';
-
-  @ViewChild('notificationPane') private notificationContainer: ElementRef;
-
-  allNotifications: Map<string, NotificationItem[]> = new Map();
-  unreadNotifications: any;
-  existingNotifications: ExistingNotification[] = [];
-  currentlySelectedNotification: ExistingNotification;
-  currentlySelectedNotificationId: string;
-
-  pipelinesWithNotificationsPresent = false;
-  notificationsLoading = false;
-
-  currentOffset = 0;
-  liveOffset = 0;
-  previousScrollHeight: number;
-
-  subscription: Subscription;
-  notificationTopic: string;
-
-  newNotificationInfo: boolean[] = [];
-
-  newEventArriving = false;
-  lastFetchTime = new Date().getTime();
-
-  constructor(private authService: AuthService,
-              private pipelineService: PipelineService,
-              public elementIconText: ElementIconText,
-              private notificationService: NotificationsService,
-              private notificationCountService: NotificationCountService,
-              private breadcrumbService: SpBreadcrumbService) {
-    this.unreadNotifications = [];
-  }
-
-  ngOnInit() {
-    this.breadcrumbService.updateBreadcrumb([{label: 'Notifications'}]);
-    this.getPipelinesWithNotifications();
-    this.subscription = timer(0, 5000).pipe(
-      filter(() => (this.currentlySelectedNotification !== undefined && this.allNotifications.size > 0)),
-      switchMap(() => this.notificationService.getNotificationsFromTime(
-        this.lastFetchTime)))
-      .subscribe((notifications) => {
-        let scrollToBottom = false;
-        if (notifications.length > 0) {
-          if ((this.notificationContainer.nativeElement.scrollHeight - this.notificationContainer.nativeElement.scrollTop) <=
-            (this.notificationContainer.nativeElement.clientHeight + 10) &&
-            (this.notificationContainer.nativeElement.scrollHeight - this.notificationContainer.nativeElement.scrollTop) >=
-            (this.notificationContainer.nativeElement.clientHeight - 10)) {
-            scrollToBottom = true;
-          }
-          this.newEventArriving = true;
-          notifications.forEach(notification => {
-            const notificationId = NotificationUtils.makeNotificationId(notification.correspondingPipelineId, notification.title);
-            const existingNots = this.allNotifications.get(notificationId);
-            existingNots.push(notification);
-            this.allNotifications.set(notificationId, existingNots);
-            if (this.currentlySelectedNotificationId === notificationId) {
-              this.liveOffset++;
-              notification.read = true;
-              setTimeout(() => {
-                this.notificationService.updateNotification(notification).subscribe();
-              }, 500);
-            } else {
-              this.newNotificationInfo[notificationId] = true;
-            }
-          });
+    @ViewChild('notificationPane') private notificationContainer: ElementRef;
+
+    allNotifications: Map<string, NotificationItem[]> = new Map();
+    unreadNotifications: any;
+    existingNotifications: ExistingNotification[] = [];
+    currentlySelectedNotification: ExistingNotification;
+    currentlySelectedNotificationId: string;
+
+    pipelinesWithNotificationsPresent = false;
+    notificationsLoading = false;
+
+    currentOffset = 0;
+    liveOffset = 0;
+    previousScrollHeight: number;
+
+    subscription: Subscription;
+    notificationTopic: string;
+
+    newNotificationInfo: boolean[] = [];
+
+    newEventArriving = false;
+    lastFetchTime = new Date().getTime();
+
+    constructor(
+        private authService: AuthService,
+        private pipelineService: PipelineService,
+        public elementIconText: ElementIconText,
+        private notificationService: NotificationsService,
+        private notificationCountService: NotificationCountService,
+        private breadcrumbService: SpBreadcrumbService,
+    ) {
+        this.unreadNotifications = [];
+    }
 
-          if (scrollToBottom) {
-            setTimeout(() => {
-              this.scrollToBottom();
+    ngOnInit() {
+        this.breadcrumbService.updateBreadcrumb([{ label: 'Notifications' }]);
+        this.getPipelinesWithNotifications();
+        this.subscription = timer(0, 5000)
+            .pipe(
+                filter(
+                    () =>
+                        this.currentlySelectedNotification !== undefined &&
+                        this.allNotifications.size > 0,
+                ),
+                switchMap(() =>
+                    this.notificationService.getNotificationsFromTime(
+                        this.lastFetchTime,
+                    ),
+                ),
+            )
+            .subscribe(notifications => {
+                let scrollToBottom = false;
+                if (notifications.length > 0) {
+                    if (
+                        this.notificationContainer.nativeElement.scrollHeight -
+                            this.notificationContainer.nativeElement
+                                .scrollTop <=
+                            this.notificationContainer.nativeElement
+                                .clientHeight +
+                                10 &&
+                        this.notificationContainer.nativeElement.scrollHeight -
+                            this.notificationContainer.nativeElement
+                                .scrollTop >=
+                            this.notificationContainer.nativeElement
+                                .clientHeight -
+                                10
+                    ) {
+                        scrollToBottom = true;
+                    }
+                    this.newEventArriving = true;
+                    notifications.forEach(notification => {
+                        const notificationId =
+                            NotificationUtils.makeNotificationId(
+                                notification.correspondingPipelineId,
+                                notification.title,
+                            );
+                        const existingNots =
+                            this.allNotifications.get(notificationId);
+                        existingNots.push(notification);
+                        this.allNotifications.set(notificationId, existingNots);
+                        if (
+                            this.currentlySelectedNotificationId ===
+                            notificationId
+                        ) {
+                            this.liveOffset++;
+                            notification.read = true;
+                            setTimeout(() => {
+                                this.notificationService
+                                    .updateNotification(notification)
+                                    .subscribe();
+                            }, 500);
+                        } else {
+                            this.newNotificationInfo[notificationId] = true;
+                        }
+                    });
+
+                    if (scrollToBottom) {
+                        setTimeout(() => {
+                            this.scrollToBottom();
+                        });
+                    }
+                }
+                this.lastFetchTime = new Date().getTime();
+                this.newEventArriving = false;
             });
-          }
-        }
-        this.lastFetchTime = new Date().getTime();
-        this.newEventArriving = false;
-      });
-  }
-
-  scrollToBottom() {
-   setTimeout(() => {
-     this.notificationContainer.nativeElement.scrollTop = this.notificationContainer.nativeElement.scrollHeight + 100;
-   }, 200);
-  }
-
-  getPipelinesWithNotifications() {
-    this.notificationsLoading = true;
-    this.pipelineService.getOwnPipelines().subscribe(pipelines => {
-      this.existingNotifications = this.getAllExistingNotifications(pipelines);
-      this.notificationsLoading = false;
-      if (this.existingNotifications.length > 0) {
-        this.pipelinesWithNotificationsPresent = true;
-        this.selectNotification(this.existingNotifications[0]);
-        this.existingNotifications.forEach(notification => {
-          this.getNotifications(notification, this.currentOffset, 10, true);
+    }
+
+    scrollToBottom() {
+        setTimeout(() => {
+            this.notificationContainer.nativeElement.scrollTop =
+                this.notificationContainer.nativeElement.scrollHeight + 100;
+        }, 200);
+    }
+
+    getPipelinesWithNotifications() {
+        this.notificationsLoading = true;
+        this.pipelineService.getOwnPipelines().subscribe(pipelines => {
+            this.existingNotifications =
+                this.getAllExistingNotifications(pipelines);
+            this.notificationsLoading = false;
+            if (this.existingNotifications.length > 0) {
+                this.pipelinesWithNotificationsPresent = true;
+                this.selectNotification(this.existingNotifications[0]);
+                this.existingNotifications.forEach(notification => {
+                    this.getNotifications(
+                        notification,
+                        this.currentOffset,
+                        10,
+                        true,
+                    );
+                });
+            }
         });
-      }
-    });
-  }
-
-  getAllExistingNotifications(pipelines: Pipeline[]): ExistingNotification[] {
-    const existingNotifications = [];
-    pipelines.forEach(pipeline => {
-      const notificationActions = pipeline.actions.filter(sink => sink.appId === NotificationsComponent.NOTIFICATIONS_APP_ID);
-      notificationActions.forEach(notificationAction => {
-        const notificationName = notificationAction
-          .staticProperties
-          .filter(sp => sp.internalName === NotificationsComponent.NOTIFICATION_TITLE_KEY)
-          .map(sp => (sp as FreeTextStaticProperty).value)[0];
-        const pipelineName = pipeline.name;
-        existingNotifications.push({
-          notificationTitle: notificationName,
-          pipelineName,
-          pipelineId: pipeline._id,
-          notificationId: NotificationUtils.makeNotificationId(pipeline._id, notificationName)
+    }
+
+    getAllExistingNotifications(pipelines: Pipeline[]): ExistingNotification[] {
+        const existingNotifications = [];
+        pipelines.forEach(pipeline => {
+            const notificationActions = pipeline.actions.filter(
+                sink =>
+                    sink.appId === NotificationsComponent.NOTIFICATIONS_APP_ID,
+            );
+            notificationActions.forEach(notificationAction => {
+                const notificationName = notificationAction.staticProperties
+                    .filter(
+                        sp =>
+                            sp.internalName ===
+                            NotificationsComponent.NOTIFICATION_TITLE_KEY,
+                    )
+                    .map(sp => (sp as FreeTextStaticProperty).value)[0];
+                const pipelineName = pipeline.name;
+                existingNotifications.push({
+                    notificationTitle: notificationName,
+                    pipelineName,
+                    pipelineId: pipeline._id,
+                    notificationId: NotificationUtils.makeNotificationId(
+                        pipeline._id,
+                        notificationName,
+                    ),
+                });
+            });
         });
-      });
-    });
-    return existingNotifications;
-  }
-
-  getNotifications(notification: ExistingNotification,
-                   offset: number,
-                   count: number,
-                   scrollToBottom: boolean) {
-    this.notificationService.getNotifications(notification, offset, count).subscribe(notifications => {
-      notifications.sort((a, b) => {
-        return (a.createdAtTimestamp - b.createdAtTimestamp);
-      });
-      const notificationId = NotificationUtils.makeNotificationId(notification.pipelineId, notification.notificationTitle);
-      if (!this.allNotifications.has(notificationId)) {
-        this.allNotifications.set(notificationId, []);
-      }
-      this.allNotifications.get(notificationId).unshift(...notifications);
-      if (scrollToBottom) {
-        setTimeout(() => {
-          this.scrollToBottom();
-        }, 500);
-      } else {
-        setTimeout(() => {
-          this.notificationContainer.nativeElement.scrollTop =
-            this.notificationContainer.nativeElement.scrollHeight - this.previousScrollHeight;
+        return existingNotifications;
+    }
+
+    getNotifications(
+        notification: ExistingNotification,
+        offset: number,
+        count: number,
+        scrollToBottom: boolean,
+    ) {
+        this.notificationService
+            .getNotifications(notification, offset, count)
+            .subscribe(notifications => {
+                notifications.sort((a, b) => {
+                    return a.createdAtTimestamp - b.createdAtTimestamp;
+                });
+                const notificationId = NotificationUtils.makeNotificationId(
+                    notification.pipelineId,
+                    notification.notificationTitle,
+                );
+                if (!this.allNotifications.has(notificationId)) {
+                    this.allNotifications.set(notificationId, []);
+                }
+                this.allNotifications
+                    .get(notificationId)
+                    .unshift(...notifications);
+                if (scrollToBottom) {
+                    setTimeout(() => {
+                        this.scrollToBottom();
+                    }, 500);
+                } else {
+                    setTimeout(() => {
+                        this.notificationContainer.nativeElement.scrollTop =
+                            this.notificationContainer.nativeElement
+                                .scrollHeight - this.previousScrollHeight;
+                    });
+                }
+                this.updateUnreadNotifications(notifications);
+            });
+    }
+
+    updateUnreadNotifications(notifications: NotificationItem[]) {
+        notifications.forEach(n => {
+            if (!n.read) {
+                n.read = true;
+                this.notificationCountService.decreaseNotificationCount();
+                this.notificationService.updateNotification(n).subscribe();
+            }
         });
-      }
-      this.updateUnreadNotifications(notifications);
-    });
-  }
-
-  updateUnreadNotifications(notifications: NotificationItem[]) {
-    notifications.forEach(n => {
-      if (!n.read) {
-        n.read = true;
-        this.notificationCountService.decreaseNotificationCount();
-        this.notificationService.updateNotification(n).subscribe();
-      }
-    });
-  }
-
-  selectNotification(notification: ExistingNotification) {
-    this.currentOffset = 0;
-    this.liveOffset = 0;
-    this.currentlySelectedNotification = notification;
-    this.currentlySelectedNotificationId = NotificationUtils.makeNotificationIdFromNotification(notification);
-    if (this.allNotifications.has(this.currentlySelectedNotificationId)) {
-      this.updateUnreadNotifications(this.allNotifications.get(this.currentlySelectedNotificationId));
     }
-    this.newNotificationInfo[this.currentlySelectedNotificationId] = false;
-    this.notificationCountService.lockIncreaseUpdateForId(this.currentlySelectedNotificationId);
-    if (this.notificationContainer) {
-      this.scrollToBottom();
+
+    selectNotification(notification: ExistingNotification) {
+        this.currentOffset = 0;
+        this.liveOffset = 0;
+        this.currentlySelectedNotification = notification;
+        this.currentlySelectedNotificationId =
+            NotificationUtils.makeNotificationIdFromNotification(notification);
+        if (this.allNotifications.has(this.currentlySelectedNotificationId)) {
+            this.updateUnreadNotifications(
+                this.allNotifications.get(this.currentlySelectedNotificationId),
+            );
+        }
+        this.newNotificationInfo[this.currentlySelectedNotificationId] = false;
+        this.notificationCountService.lockIncreaseUpdateForId(
+            this.currentlySelectedNotificationId,
+        );
+        if (this.notificationContainer) {
+            this.scrollToBottom();
+        }
     }
-  }
-
-  onScroll() {
-    if (this.notificationContainer.nativeElement.scrollTop === 0) {
-      this.currentOffset += 10;
-      this.previousScrollHeight = this.notificationContainer.nativeElement.scrollHeight;
-      const currentNotifications = this.allNotifications.get(this.currentlySelectedNotificationId);
-      this.getNotifications(this.currentlySelectedNotification, currentNotifications.length + this.liveOffset, 10, false);
+
+    onScroll() {
+        if (this.notificationContainer.nativeElement.scrollTop === 0) {
+            this.currentOffset += 10;
+            this.previousScrollHeight =
+                this.notificationContainer.nativeElement.scrollHeight;
+            const currentNotifications = this.allNotifications.get(
+                this.currentlySelectedNotificationId,
+            );
+            this.getNotifications(
+                this.currentlySelectedNotification,
+                currentNotifications.length + this.liveOffset,
+                10,
+                false,
+            );
+        }
     }
-  }
 
-  ngOnDestroy(): void {
-    if (this.subscription) {
-      this.subscription.unsubscribe();
+    ngOnDestroy(): void {
+        if (this.subscription) {
+            this.subscription.unsubscribe();
+        }
+        this.notificationCountService.unlockIncreaseUpdate();
     }
-    this.notificationCountService.unlockIncreaseUpdate();
-  }
 }
diff --git a/ui/src/app/notifications/notifications.module.ts b/ui/src/app/notifications/notifications.module.ts
index 1882aac78..83cc79547 100644
--- a/ui/src/app/notifications/notifications.module.ts
+++ b/ui/src/app/notifications/notifications.module.ts
@@ -38,23 +38,12 @@ import { PlatformServicesModule } from '@streampipes/platform-services';
         FlexLayoutModule,
         CustomMaterialModule,
         FormsModule,
-        PlatformServicesModule
+        PlatformServicesModule,
     ],
-    declarations: [
-        NotificationsComponent,
-        NotificationItemComponent
-    ],
-    providers: [
-        NotificationsService
-    ],
-    exports: [
-        NotificationsComponent
-    ]
+    declarations: [NotificationsComponent, NotificationItemComponent],
+    providers: [NotificationsService],
+    exports: [NotificationsComponent],
 })
 export class NotificationModule {
-
-  constructor() {
-  }
-
+    constructor() {}
 }
-
diff --git a/ui/src/app/notifications/service/notifications.service.ts b/ui/src/app/notifications/service/notifications.service.ts
index f359b472d..8433f4584 100644
--- a/ui/src/app/notifications/service/notifications.service.ts
+++ b/ui/src/app/notifications/service/notifications.service.ts
@@ -19,7 +19,7 @@ import { HttpClient } from '@angular/common/http';
 import { Observable } from 'rxjs';
 import {
     ExistingNotification,
-    NotificationItem
+    NotificationItem,
 } from '../model/notifications.model';
 import { Injectable } from '@angular/core';
 import { NotificationUtils } from '../utils/notifications.utils';
@@ -28,41 +28,61 @@ import { PlatformServicesCommons } from '@streampipes/platform-services';
 
 @Injectable()
 export class NotificationsService {
+    constructor(
+        private http: HttpClient,
+        private platformServicesCommons: PlatformServicesCommons,
+    ) {}
 
-    constructor(private http: HttpClient,
-                private platformServicesCommons: PlatformServicesCommons) {
-    }
-
-    getNotificationsFromTime(startTime: number): Observable<NotificationItem[]> {
+    getNotificationsFromTime(
+        startTime: number,
+    ): Observable<NotificationItem[]> {
         return this.http
-          .get(this.notificationUrl
-            + '/time'
-            + '?'
-            + 'startTime=' + startTime)
-          .pipe(map(data => {
-              return data as NotificationItem[];
-          }));
+            .get(
+                this.notificationUrl + '/time' + '?' + 'startTime=' + startTime,
+            )
+            .pipe(
+                map(data => {
+                    return data as NotificationItem[];
+                }),
+            );
     }
 
-    getNotifications(existingNotification: ExistingNotification, offset: number, limit: number): Observable<NotificationItem[]> {
+    getNotifications(
+        existingNotification: ExistingNotification,
+        offset: number,
+        limit: number,
+    ): Observable<NotificationItem[]> {
         return this.http
-            .get(this.notificationUrl
-                + '/offset'
-                + '?'
-                + 'notificationType=' + NotificationUtils.makeNotificationIdFromNotification(existingNotification)
-                + '&'
-                + 'offset=' + offset
-                + '&'
-                + 'count=' + limit)
-            .pipe(map(data => {
-                return data as NotificationItem[];
-            }));
+            .get(
+                this.notificationUrl +
+                    '/offset' +
+                    '?' +
+                    'notificationType=' +
+                    NotificationUtils.makeNotificationIdFromNotification(
+                        existingNotification,
+                    ) +
+                    '&' +
+                    'offset=' +
+                    offset +
+                    '&' +
+                    'count=' +
+                    limit,
+            )
+            .pipe(
+                map(data => {
+                    return data as NotificationItem[];
+                }),
+            );
     }
 
     updateNotification(notificationItem: NotificationItem): Observable<any> {
-        return this.http.put(this.notificationUrl + '/' + notificationItem._id, notificationItem, {
-            headers: { ignoreLoadingBar: '' }
-        });
+        return this.http.put(
+            this.notificationUrl + '/' + notificationItem._id,
+            notificationItem,
+            {
+                headers: { ignoreLoadingBar: '' },
+            },
+        );
     }
 
     private get notificationUrl() {
diff --git a/ui/src/app/notifications/utils/notifications.utils.ts b/ui/src/app/notifications/utils/notifications.utils.ts
index 8fb001357..da7cda839 100644
--- a/ui/src/app/notifications/utils/notifications.utils.ts
+++ b/ui/src/app/notifications/utils/notifications.utils.ts
@@ -18,9 +18,13 @@
 import { ExistingNotification } from '../model/notifications.model';
 
 export class NotificationUtils {
-
-    static makeNotificationIdFromNotification(existingNotification: ExistingNotification): string {
-       return this.makeNotificationId(existingNotification.pipelineId, existingNotification.notificationTitle);
+    static makeNotificationIdFromNotification(
+        existingNotification: ExistingNotification,
+    ): string {
+        return this.makeNotificationId(
+            existingNotification.pipelineId,
+            existingNotification.notificationTitle,
+        );
     }
 
     static makeNotificationId(pipelineId: string, notificationTitle: string) {