You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by ri...@apache.org on 2020/03/16 12:31:02 UTC

[incubator-streampipes] branch dev updated (5be3b76 -> fd8bba6)

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

riemer pushed a change to branch dev
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git.


    from 5be3b76  Change type check in adapter creation
     new c27b3d1  Refactor NotificationsModule to Angular 9 module
     new b914db7  Fix layout of dashboard component
     new fd8bba6  Merge branch 'dev' of github.com:apache/incubator-streampipes into dev

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../org/apache/streampipes/model/Notification.java |   9 ++
 .../model/base/InvocableStreamPipesEntity.java     |  12 ++
 .../manager/setup/CouchDbInstallationStep.java     |  31 ++++-
 .../apache/streampipes/rest/api/INotification.java |   2 +-
 .../apache/streampipes/rest/impl/Notification.java |   7 +-
 .../rest/notifications/NotificationListener.java   |   2 +-
 .../storage/api/INotificationStorage.java          |   2 +-
 .../couchdb/impl/NotificationStorageImpl.java      |  26 +++-
 .../apache/streampipes/vocabulary/StreamPipes.java |   1 +
 .../wrapper/context/RuntimeContext.java            |   2 +
 .../context/SpEventProcessorRuntimeContext.java    |   9 +-
 .../wrapper/context/SpEventSinkRuntimeContext.java |   6 +-
 .../wrapper/context/SpRuntimeContext.java          |  11 +-
 .../runtime/EventProcessorRuntimeParams.java       |   3 +-
 .../params/runtime/EventSinkRuntimeParams.java     |   3 +-
 ui/deployment/state.config.mst                     |   3 +-
 ui/deployment/toolbar.controller.mst               |   2 +-
 ui/src/app/core/working.state.config.ts            |   2 +-
 .../components/grid/dashboard-grid.component.css   |   6 +
 .../components/panel/dashboard-panel.component.css |   6 +
 .../panel/dashboard-panel.component.html           |   6 +-
 ui/src/app/dashboard/dashboard.component.css       |   9 ++
 ui/src/app/dashboard/dashboard.component.html      |   2 +-
 ui/src/app/dashboard/services/dashboard.service.ts |   1 -
 ui/src/app/editor/editor.controller.ts             |   5 +-
 .../components/notification-item.component.html}   |  15 ++-
 .../components/notification-item.component.scss}   |  42 ++++--
 .../components/notification-item.component.ts}     |  27 ++--
 .../model/notifications.model.ts}                  |  24 ++--
 .../app/notifications/notifications.component.html |  67 ++++++++++
 .../app/notifications/notifications.component.scss | 118 +++++++++++++++++
 .../app/notifications/notifications.component.ts   | 144 +++++++++++++++++++++
 .../app/notifications/notifications.controller.ts  |  65 ----------
 ui/src/app/notifications/notifications.html        |  72 -----------
 ui/src/app/notifications/notifications.module.ts   |  54 +++++++-
 .../notifications/service/notifications.service.ts |  55 ++++++++
 .../utils/notifications.utils.ts}                  |  18 +--
 ui/src/assets/templates/streampipes.html           |  10 +-
 ui/src/index.html                                  |   2 +-
 ui/src/scss/sp/main.scss                           |   2 +-
 40 files changed, 661 insertions(+), 222 deletions(-)
 copy ui/src/app/{dashboard/components/standalone/standalone-dashboard.component.html => notifications/components/notification-item.component.html} (73%)
 copy ui/src/app/{dashboard/components/standalone/standalone-dashboard.component.css => notifications/components/notification-item.component.scss} (57%)
 copy ui/src/app/{dashboard/sdk/matching/schema-match.ts => notifications/components/notification-item.component.ts} (56%)
 copy ui/src/app/{dashboard/components/widgets/html/html-widget.component.css => notifications/model/notifications.model.ts} (71%)
 create mode 100644 ui/src/app/notifications/notifications.component.html
 create mode 100644 ui/src/app/notifications/notifications.component.scss
 create mode 100644 ui/src/app/notifications/notifications.component.ts
 delete mode 100644 ui/src/app/notifications/notifications.controller.ts
 delete mode 100644 ui/src/app/notifications/notifications.html
 create mode 100644 ui/src/app/notifications/service/notifications.service.ts
 copy ui/src/app/{dashboard/sdk/matching/schema-match.ts => notifications/utils/notifications.utils.ts} (62%)


[incubator-streampipes] 03/03: Merge branch 'dev' of github.com:apache/incubator-streampipes into dev

Posted by ri...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

riemer pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git

commit fd8bba692465655a1b76a046b16d7703ae5b58d0
Merge: b914db7 5be3b76
Author: Dominik Riemer <ri...@fzi.de>
AuthorDate: Mon Mar 16 13:30:41 2020 +0100

    Merge branch 'dev' of github.com:apache/incubator-streampipes into dev

 ui/src/app/connect/model/DataStreamDescription.ts  |   2 +-
 .../connect/new-adapter/new-adapter.component.ts   | 186 +++++++++++----------
 .../app/connect/schema-editor/model/EventSchema.ts |  14 +-
 3 files changed, 102 insertions(+), 100 deletions(-)


[incubator-streampipes] 02/03: Fix layout of dashboard component

Posted by ri...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

riemer pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git

commit b914db785b357856dc47c46a80cd0aa9e34c686e
Author: Dominik Riemer <ri...@fzi.de>
AuthorDate: Mon Mar 16 13:30:28 2020 +0100

    Fix layout of dashboard component
---
 .../app/dashboard/components/grid/dashboard-grid.component.css   | 6 ++++++
 .../app/dashboard/components/panel/dashboard-panel.component.css | 6 ++++++
 .../dashboard/components/panel/dashboard-panel.component.html    | 6 +++---
 ui/src/app/dashboard/dashboard.component.css                     | 9 +++++++++
 ui/src/app/dashboard/dashboard.component.html                    | 2 +-
 5 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/ui/src/app/dashboard/components/grid/dashboard-grid.component.css b/ui/src/app/dashboard/components/grid/dashboard-grid.component.css
index 6368cea..791a047 100644
--- a/ui/src/app/dashboard/components/grid/dashboard-grid.component.css
+++ b/ui/src/app/dashboard/components/grid/dashboard-grid.component.css
@@ -22,4 +22,10 @@ gridster ::ng-deep {
 
 gridster.edit ::ng-deep {
     background: #d3d3d3;
+}
+
+gridster.scrollVertical ::ng-deep {
+    min-height: 100%;
+    display: flex;
+    flex: 1 1 100%;
 }
\ No newline at end of file
diff --git a/ui/src/app/dashboard/components/panel/dashboard-panel.component.css b/ui/src/app/dashboard/components/panel/dashboard-panel.component.css
index 1faa4d1..178a2de 100644
--- a/ui/src/app/dashboard/components/panel/dashboard-panel.component.css
+++ b/ui/src/app/dashboard/components/panel/dashboard-panel.component.css
@@ -23,3 +23,9 @@
 .h-100 {
     height:100%;
 }
+
+.dashboard-grid {
+    display:flex;
+    flex-direction: column;
+    flex: 1 1 100%;
+}
diff --git a/ui/src/app/dashboard/components/panel/dashboard-panel.component.html b/ui/src/app/dashboard/components/panel/dashboard-panel.component.html
index 682418b..42a05c1 100644
--- a/ui/src/app/dashboard/components/panel/dashboard-panel.component.html
+++ b/ui/src/app/dashboard/components/panel/dashboard-panel.component.html
@@ -16,8 +16,8 @@
   ~
   -->
 
-<div fxFlex="100" fxLayout="column" class="m-20">
-    <div fxLayout="row wrap" style="margin-bottom:20px;" *ngIf="editMode">
+<div fxFlex="100" fxLayout="column">
+    <div fxLayout="row wrap" class="m-20" style="margin-bottom:20px;" *ngIf="editMode">
         <button mat-button mat-raised-button color="primary" (click)="updateDashboardAndCloseEditMode()"
                 style="margin-right:10px;">Save
         </button>
@@ -31,5 +31,5 @@
     <dashboard-grid [editMode]="editMode" [dashboard]="dashboard"
                     (updateCallback)="updateAndQueueItemForDeletion($event)"
                     (deleteCallback)="removeAndQueueItemForDeletion($event)"
-                    class="h-100"></dashboard-grid>
+                    class="h-100 dashboard-grid"></dashboard-grid>
 </div>
\ No newline at end of file
diff --git a/ui/src/app/dashboard/dashboard.component.css b/ui/src/app/dashboard/dashboard.component.css
index 7eaab26..8e7687a 100644
--- a/ui/src/app/dashboard/dashboard.component.css
+++ b/ui/src/app/dashboard/dashboard.component.css
@@ -18,4 +18,13 @@
 
 .mr-20 {
     margin-right:20px;
+}
+
+.dashboard-panel {
+    height: 100%;
+    flex-direction: column;
+    box-sizing: border-box;
+    display: flex;
+    flex: 1 1 100%;
+    overflow-y: auto;
 }
\ No newline at end of file
diff --git a/ui/src/app/dashboard/dashboard.component.html b/ui/src/app/dashboard/dashboard.component.html
index 6bb288d..11cc2a0 100644
--- a/ui/src/app/dashboard/dashboard.component.html
+++ b/ui/src/app/dashboard/dashboard.component.html
@@ -44,7 +44,7 @@
 
     </dashboard-overview>
     <dashboard-panel fxLayout="column" [(editMode)]="editMode" [dashboard]="selectedDashboard"
-                     style="height:100%;" *ngIf="dashboardTabSelected">
+                     class="dashboard-panel" *ngIf="dashboardTabSelected">
 
     </dashboard-panel>
     </div>


[incubator-streampipes] 01/03: Refactor NotificationsModule to Angular 9 module

Posted by ri...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

riemer pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git

commit c27b3d1974545d58cbbd826d3eca3bf607074176
Author: Dominik Riemer <ri...@fzi.de>
AuthorDate: Mon Mar 16 11:06:18 2020 +0100

    Refactor NotificationsModule to Angular 9 module
---
 .../org/apache/streampipes/model/Notification.java |   9 ++
 .../model/base/InvocableStreamPipesEntity.java     |  12 ++
 .../manager/setup/CouchDbInstallationStep.java     |  31 ++++-
 .../apache/streampipes/rest/api/INotification.java |   2 +-
 .../apache/streampipes/rest/impl/Notification.java |   7 +-
 .../rest/notifications/NotificationListener.java   |   2 +-
 .../storage/api/INotificationStorage.java          |   2 +-
 .../couchdb/impl/NotificationStorageImpl.java      |  26 +++-
 .../apache/streampipes/vocabulary/StreamPipes.java |   1 +
 .../wrapper/context/RuntimeContext.java            |   2 +
 .../context/SpEventProcessorRuntimeContext.java    |   9 +-
 .../wrapper/context/SpEventSinkRuntimeContext.java |   6 +-
 .../wrapper/context/SpRuntimeContext.java          |  11 +-
 .../runtime/EventProcessorRuntimeParams.java       |   3 +-
 .../params/runtime/EventSinkRuntimeParams.java     |   3 +-
 ui/deployment/state.config.mst                     |   3 +-
 ui/deployment/toolbar.controller.mst               |   2 +-
 ui/src/app/core/working.state.config.ts            |   2 +-
 ui/src/app/dashboard/services/dashboard.service.ts |   1 -
 ui/src/app/editor/editor.controller.ts             |   5 +-
 .../components/notification-item.component.html    |  28 ++++
 .../components/notification-item.component.scss    |  55 ++++++++
 .../components/notification-item.component.ts      |  39 ++++++
 .../app/notifications/model/notifications.model.ts |  32 +++++
 .../app/notifications/notifications.component.html |  67 ++++++++++
 .../app/notifications/notifications.component.scss | 118 +++++++++++++++++
 .../app/notifications/notifications.component.ts   | 144 +++++++++++++++++++++
 .../app/notifications/notifications.controller.ts  |  65 ----------
 ui/src/app/notifications/notifications.html        |  72 -----------
 ui/src/app/notifications/notifications.module.ts   |  54 +++++++-
 .../notifications/service/notifications.service.ts |  55 ++++++++
 .../app/notifications/utils/notifications.utils.ts |  30 +++++
 ui/src/assets/templates/streampipes.html           |  10 +-
 ui/src/index.html                                  |   2 +-
 ui/src/scss/sp/main.scss                           |   2 +-
 35 files changed, 737 insertions(+), 175 deletions(-)

diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/Notification.java b/streampipes-model/src/main/java/org/apache/streampipes/model/Notification.java
index e050ee1..c161c0d 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/Notification.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/Notification.java
@@ -30,6 +30,7 @@ public class Notification {
   private String title;
   private Date createdAt;
   private String targetedAt;
+  private String correspondingPipelineId;
 
   private String message;
 
@@ -100,4 +101,12 @@ public class Notification {
   public void setRead(Boolean read) {
     this.read = read;
   }
+
+  public String getCorrespondingPipelineId() {
+    return correspondingPipelineId;
+  }
+
+  public void setCorrespondingPipelineId(String correspondingPipelineId) {
+    this.correspondingPipelineId = correspondingPipelineId;
+  }
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/base/InvocableStreamPipesEntity.java b/streampipes-model/src/main/java/org/apache/streampipes/model/base/InvocableStreamPipesEntity.java
index e289eb9..6736149 100644
--- a/streampipes-model/src/main/java/org/apache/streampipes/model/base/InvocableStreamPipesEntity.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/base/InvocableStreamPipesEntity.java
@@ -62,6 +62,9 @@ public abstract class InvocableStreamPipesEntity extends NamedStreamPipesEntity
   @RdfProperty(StreamPipes.CORRESPONDING_PIPELINE)
   private String correspondingPipeline;
 
+  @RdfProperty(StreamPipes.CORRESPONDING_USER)
+  private String correspondingUser;
+
   private List<SpDataStream> streamRequirements;
 
   private boolean configured;
@@ -76,6 +79,7 @@ public abstract class InvocableStreamPipesEntity extends NamedStreamPipesEntity
     this.correspondingPipeline = other.getCorrespondingPipeline();
     this.inputStreams = new Cloner().streams(other.getInputStreams());
     this.configured = other.isConfigured();
+    this.correspondingUser = other.getCorrespondingUser();
     if (other.getStreamRequirements() != null) {
       this.streamRequirements = new Cloner().streams(other.getStreamRequirements());
     }
@@ -161,6 +165,14 @@ public abstract class InvocableStreamPipesEntity extends NamedStreamPipesEntity
     this.statusInfoSettings = statusInfoSettings;
   }
 
+  public String getCorrespondingUser() {
+    return correspondingUser;
+  }
+
+  public void setCorrespondingUser(String correspondingUser) {
+    this.correspondingUser = correspondingUser;
+  }
+
   //public Logger getLogger(Class clazz, PeConfig peConfig) {
   public Logger getLogger(Class clazz) {
     //	return LoggerFactory.getPeLogger(clazz, getCorrespondingPipeline(), getUri(), peConfig);
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/CouchDbInstallationStep.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/CouchDbInstallationStep.java
index e816651..18855dd 100644
--- a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/CouchDbInstallationStep.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/CouchDbInstallationStep.java
@@ -35,6 +35,10 @@ public class CouchDbInstallationStep implements InstallationStep {
             Collections.singletonList("8099/api/v1/admin@streampipes.org/master/sources/");
     private static final String initRdfEndpointHost = "http://localhost:";
 
+    private static final String PREPARING_NOTIFICATIONS_TEXT = "Preparing database " +
+            "'notifications'...";
+    private static final String PREPARING_USERS_TEXT = "Preparing database 'users'...";
+
     public CouchDbInstallationStep() {
 
     }
@@ -83,6 +87,7 @@ public class CouchDbInstallationStep implements InstallationStep {
         List<Message> result = new ArrayList<>();
         result.add(addUserView());
         result.add(addConnectionView());
+        result.add(addNotificationView());
         return result;
     }
 
@@ -95,6 +100,26 @@ public class CouchDbInstallationStep implements InstallationStep {
         return Notifications.success("Discovering pipeline element endpoints...");
     }
 
+    private Message addNotificationView() {
+        try {
+            DesignDocument userDocument = prepareDocument("_design/notificationtypes");
+            Map<String, MapReduce> views = new HashMap<>();
+
+            MapReduce notificationTypeFunction = new MapReduce();
+            notificationTypeFunction.setMap("function (doc) { var vizName = doc.title.replace(/\\s/g, '-'); var indexName = doc.correspondingPipelineId + '-' + vizName; emit(indexName, doc);}");
+
+            views.put("notificationtypes", notificationTypeFunction);
+
+            userDocument.setViews(views);
+            Response resp = Utils.getCouchDbNotificationClient().design().synchronizeWithDb(userDocument);
+
+            if (resp.getError() != null) return Notifications.error(PREPARING_NOTIFICATIONS_TEXT);
+            else return Notifications.success(PREPARING_NOTIFICATIONS_TEXT);
+        } catch (Exception e) {
+            return Notifications.error(PREPARING_NOTIFICATIONS_TEXT);
+        }
+    }
+
     private Message addUserView() {
         try {
             DesignDocument userDocument = prepareDocument("_design/users");
@@ -112,10 +137,10 @@ public class CouchDbInstallationStep implements InstallationStep {
             userDocument.setViews(views);
             Response resp = Utils.getCouchDbUserClient().design().synchronizeWithDb(userDocument);
 
-            if (resp.getError() != null) return Notifications.error("Preparing database 'users'...");
-            else return Notifications.success("Preparing database 'users'...");
+            if (resp.getError() != null) return Notifications.error(PREPARING_USERS_TEXT);
+            else return Notifications.success(PREPARING_USERS_TEXT);
         } catch (Exception e) {
-            return Notifications.error("Preparing database 'users'...");
+            return Notifications.error(PREPARING_USERS_TEXT);
         }
     }
 
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/api/INotification.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/api/INotification.java
index 419dd31..75612fe 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/api/INotification.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/api/INotification.java
@@ -22,7 +22,7 @@ import javax.ws.rs.core.Response;
 
 public interface INotification {
 
-	Response getNotifications();
+	Response getNotifications(String notificationTypeId, Integer offset, Integer count);
 
 	Response getUnreadNotifications();
 
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Notification.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Notification.java
index 527d363..b653ba7 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Notification.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/Notification.java
@@ -28,6 +28,7 @@ import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
@@ -38,9 +39,11 @@ public class Notification extends AbstractRestInterface implements INotification
     @Produces(MediaType.APPLICATION_JSON)
     @GsonWithIds
     @Override
-    public Response getNotifications() {
+    public Response getNotifications(@QueryParam("notificationType") String notificationTypeId,
+                                     @QueryParam("offset") Integer offset,
+                                     @QueryParam("count") Integer count) {
         return ok(getNotificationStorage()
-                .getAllNotifications());
+                .getAllNotifications(notificationTypeId, offset, count));
     }
 
     @GET
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/notifications/NotificationListener.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/notifications/NotificationListener.java
index 7d0c9bd..4e59eee 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/notifications/NotificationListener.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/notifications/NotificationListener.java
@@ -25,7 +25,7 @@ import javax.servlet.ServletContextListener;
 
 public class NotificationListener implements ServletContextListener {
 
-  private static final String internalNotificationTopic = "org.apache.streampipes.notifications";
+  private static final String internalNotificationTopic = "org.apache.streampipes.notifications.*";
 
 
   @Override
diff --git a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INotificationStorage.java b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INotificationStorage.java
index 3a0c2d7..40edf9f 100644
--- a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INotificationStorage.java
+++ b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INotificationStorage.java
@@ -26,7 +26,7 @@ public interface INotificationStorage {
 
   Notification getNotification(String notificationId);
 
-  List<Notification> getAllNotifications();
+  List<Notification> getAllNotifications(String notificationTypeId, Integer offset, Integer count);
 
   List<Notification> getUnreadNotifications();
 
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/NotificationStorageImpl.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/NotificationStorageImpl.java
index c9bcb18..dfc8e11 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/NotificationStorageImpl.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/NotificationStorageImpl.java
@@ -18,12 +18,14 @@
 
 package org.apache.streampipes.storage.couchdb.impl;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
 import org.apache.streampipes.model.Notification;
 import org.apache.streampipes.storage.api.INotificationStorage;
 import org.apache.streampipes.storage.couchdb.dao.AbstractDao;
 import org.apache.streampipes.storage.couchdb.utils.Utils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.List;
 import java.util.stream.Collectors;
@@ -43,8 +45,24 @@ public class NotificationStorageImpl extends AbstractDao<Notification> implement
   }
 
   @Override
-  public List<Notification> getAllNotifications() {
-    return findAll();
+  public List<Notification> getAllNotifications(String notificationTypeId,
+                                                Integer offset,
+                                                Integer count) {
+    Gson gson = couchDbClientSupplier.get().getGson();
+    List<JsonObject> notifications =
+            couchDbClientSupplier
+                    .get()
+                    .view("notificationtypes/notificationtypes")
+                    .key(notificationTypeId)
+                    .includeDocs(true)
+                    .skip(offset)
+                    .limit(count)
+                    .query(JsonObject.class);
+
+    return notifications
+            .stream()
+            .map(notification -> gson.fromJson(notification, Notification.class))
+            .collect(Collectors.toList());
   }
 
   @Override
diff --git a/streampipes-vocabulary/src/main/java/org/apache/streampipes/vocabulary/StreamPipes.java b/streampipes-vocabulary/src/main/java/org/apache/streampipes/vocabulary/StreamPipes.java
index 3fca213..06e8f36 100644
--- a/streampipes-vocabulary/src/main/java/org/apache/streampipes/vocabulary/StreamPipes.java
+++ b/streampipes-vocabulary/src/main/java/org/apache/streampipes/vocabulary/StreamPipes.java
@@ -378,4 +378,5 @@ public class StreamPipes {
   public static final String SELECTED_COLOR = NS + "hasSelectedColor";
   public static final String HAS_WIDGET_ICON_NAME = NS + "hasWidgetIconName";
   public static final String HAS_WIDGET_DESCRIPTION = NS + "hasWidgetDescription";
+  public static final String CORRESPONDING_USER = NS + "hasCorrespondingUser";
 }
diff --git a/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/context/RuntimeContext.java b/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/context/RuntimeContext.java
index 725f3b8..83c2580 100644
--- a/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/context/RuntimeContext.java
+++ b/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/context/RuntimeContext.java
@@ -30,4 +30,6 @@ public interface RuntimeContext {
   List<SchemaInfo> getInputSchemaInfo();
 
   List<SourceInfo> getInputSourceInfo();
+
+  String getCorrespondingUser();
 }
diff --git a/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/context/SpEventProcessorRuntimeContext.java b/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/context/SpEventProcessorRuntimeContext.java
index bf5349c..a8159fe 100644
--- a/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/context/SpEventProcessorRuntimeContext.java
+++ b/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/context/SpEventProcessorRuntimeContext.java
@@ -29,9 +29,12 @@ public class SpEventProcessorRuntimeContext extends SpRuntimeContext implements
   private SchemaInfo outputSchemaInfo;
   private SourceInfo outputSourceInfo;
 
-  public SpEventProcessorRuntimeContext(List<SourceInfo> inputSourceInfo, List<SchemaInfo>
-          inputSchemaInfo, SourceInfo outputSourceInfo, SchemaInfo outputSchemaInfo) {
-    super(inputSourceInfo, inputSchemaInfo);
+  public SpEventProcessorRuntimeContext(List<SourceInfo> inputSourceInfo,
+                                        List<SchemaInfo> inputSchemaInfo,
+                                        SourceInfo outputSourceInfo,
+                                        SchemaInfo outputSchemaInfo,
+                                        String correspondingUser) {
+    super(inputSourceInfo, inputSchemaInfo, correspondingUser);
     this.outputSchemaInfo = outputSchemaInfo;
     this.outputSourceInfo = outputSourceInfo;
   }
diff --git a/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/context/SpEventSinkRuntimeContext.java b/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/context/SpEventSinkRuntimeContext.java
index 4899f51..19c79aa 100644
--- a/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/context/SpEventSinkRuntimeContext.java
+++ b/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/context/SpEventSinkRuntimeContext.java
@@ -26,7 +26,9 @@ import java.util.List;
 public class SpEventSinkRuntimeContext extends SpRuntimeContext implements
         EventSinkRuntimeContext, Serializable {
 
-  public SpEventSinkRuntimeContext(List<SourceInfo> sourceInfo, List<SchemaInfo> inputSchemaInfo) {
-    super(sourceInfo, inputSchemaInfo);
+  public SpEventSinkRuntimeContext(List<SourceInfo> sourceInfo,
+                                   List<SchemaInfo> inputSchemaInfo,
+                                   String correspondingUser) {
+    super(sourceInfo, inputSchemaInfo, correspondingUser);
   }
 }
diff --git a/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/context/SpRuntimeContext.java b/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/context/SpRuntimeContext.java
index b31ce09..40b9f34 100644
--- a/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/context/SpRuntimeContext.java
+++ b/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/context/SpRuntimeContext.java
@@ -27,10 +27,14 @@ public class SpRuntimeContext implements RuntimeContext {
 
   private List<SchemaInfo> inputSchemaInfo;
   private List<SourceInfo> sourceInfo;
+  private String correspondingUser;
 
-  public SpRuntimeContext(List<SourceInfo> sourceInfo, List<SchemaInfo> inputSchemaInfo) {
+  public SpRuntimeContext(List<SourceInfo> sourceInfo,
+                          List<SchemaInfo> inputSchemaInfo,
+                          String correspondingUser) {
     this.inputSchemaInfo = inputSchemaInfo;
     this.sourceInfo = sourceInfo;
+    this.correspondingUser = correspondingUser;
   }
 
   public SpRuntimeContext() {
@@ -52,4 +56,9 @@ public class SpRuntimeContext implements RuntimeContext {
   public List<SourceInfo> getInputSourceInfo() {
     return sourceInfo;
   }
+
+  @Override
+  public String getCorrespondingUser() {
+    return correspondingUser;
+  }
 }
diff --git a/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/params/runtime/EventProcessorRuntimeParams.java b/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/params/runtime/EventProcessorRuntimeParams.java
index 7ceda55..3160e9c 100644
--- a/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/params/runtime/EventProcessorRuntimeParams.java
+++ b/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/params/runtime/EventProcessorRuntimeParams.java
@@ -34,7 +34,8 @@ public class EventProcessorRuntimeParams<B extends EventProcessorBindingParams>
   protected EventProcessorRuntimeContext makeRuntimeContext() {
     return new SpEventProcessorRuntimeContext(getSourceInfo(),
             getSchemaInfo(), bindingParams.getOutputStreamParams()
-                    .getSourceInfo(), bindingParams.getOutputStreamParams().getSchemaInfo());
+                    .getSourceInfo(), bindingParams.getOutputStreamParams().getSchemaInfo(),
+            bindingParams.getGraph().getCorrespondingUser());
   }
 
 }
diff --git a/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/params/runtime/EventSinkRuntimeParams.java b/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/params/runtime/EventSinkRuntimeParams.java
index f54a0c0..0286991 100644
--- a/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/params/runtime/EventSinkRuntimeParams.java
+++ b/streampipes-wrapper/src/main/java/org/apache/streampipes/wrapper/params/runtime/EventSinkRuntimeParams.java
@@ -32,7 +32,8 @@ public class EventSinkRuntimeParams<B extends EventSinkBindingParams> extends
 
   @Override
   protected EventSinkRuntimeContext makeRuntimeContext() {
-    return new SpEventSinkRuntimeContext(getSourceInfo(), getSchemaInfo());
+    return new SpEventSinkRuntimeContext(getSourceInfo(), getSchemaInfo(),
+            bindingParams.getGraph().getCorrespondingUser());
   }
 
 }
diff --git a/ui/deployment/state.config.mst b/ui/deployment/state.config.mst
index 58a32bd..330e598 100644
--- a/ui/deployment/state.config.mst
+++ b/ui/deployment/state.config.mst
@@ -26,6 +26,7 @@ import { HomeComponent } from '../home/home.component';
 import { InfoComponent } from '../info/info.component';
 import { AppContainerComponent } from '../app-container/app-container.component';
 import { StandaloneDashboardComponent } from "../dashboard/components/standalone/standalone-dashboard.component";
+import { NotificationsComponent } from "../notifications/notifications.component";
 
 export default function stateConfig($stateProvider, $urlRouterProvider) {
 
@@ -140,7 +141,7 @@ export default function stateConfig($stateProvider, $urlRouterProvider) {
             url: '/notifications',
             views: {
                 'spMain@streampipes': {
-                    template: require('../notifications/notifications.html')
+                    component: NotificationsComponent
                 }
             }
         })
diff --git a/ui/deployment/toolbar.controller.mst b/ui/deployment/toolbar.controller.mst
index 4df4a27..ac5d9fe 100644
--- a/ui/deployment/toolbar.controller.mst
+++ b/ui/deployment/toolbar.controller.mst
@@ -202,7 +202,7 @@ export class ToolbarController {
         var passcode = 'admin';
         var websocketProtocol = this.$location.protocol() === "http" ? "ws" : "wss";
         var brokerUrl = websocketProtocol + '://' + this.$location.host() + ':' + this.$location.port() + '/streampipes/ws';
-        var inputTopic = '/topic/org.apache.streampipes.notifications';
+        var inputTopic = '/topic/org.apache.streampipes.notifications.' + this.AuthStatusService.email;
 
         let stompClient = new Client({
             brokerURL: brokerUrl,
diff --git a/ui/src/app/core/working.state.config.ts b/ui/src/app/core/working.state.config.ts
index 786b1e4..3c2ed5a 100644
--- a/ui/src/app/core/working.state.config.ts
+++ b/ui/src/app/core/working.state.config.ts
@@ -122,7 +122,7 @@ export default function stateConfig($stateProvider, $urlRouterProvider) {
       url: '/notifications',
       views: {
         'spMain@streampipes': {
-          templateUrl: '../notifications/notifications.html',
+          templateUrl: '../notifications/notifications.component.html',
           controller: 'NotificationsCtrl',
         },
       },
diff --git a/ui/src/app/dashboard/services/dashboard.service.ts b/ui/src/app/dashboard/services/dashboard.service.ts
index 4cf5fca..a4f1d63 100644
--- a/ui/src/app/dashboard/services/dashboard.service.ts
+++ b/ui/src/app/dashboard/services/dashboard.service.ts
@@ -25,7 +25,6 @@ import {Dashboard} from "../models/dashboard.model";
 import {TsonLdSerializerService} from "../../platform-services/tsonld-serializer.service";
 import {DashboardWidget} from "../../core-model/dashboard/DashboardWidget";
 import {VisualizablePipeline} from "../../core-model/dashboard/VisualizablePipeline";
-import {RestApi} from "../../services/rest-api.service";
 
 @Injectable()
 export class DashboardService {
diff --git a/ui/src/app/editor/editor.controller.ts b/ui/src/app/editor/editor.controller.ts
index f319c18..320efa0 100644
--- a/ui/src/app/editor/editor.controller.ts
+++ b/ui/src/app/editor/editor.controller.ts
@@ -17,6 +17,7 @@
  */
 
 import * as angular from 'angular';
+import {AuthStatusService} from "../services/auth-status.service";
 
 export class EditorCtrl {
 
@@ -26,7 +27,7 @@ export class EditorCtrl {
     $window: any;
     JsplumbBridge: any;
     EditorDialogManager: any;
-    AuthStatusService: any;
+    AuthStatusService: AuthStatusService;
     currentElements: any;
     allElements: any;
     currentModifiedPipelineId: any;
@@ -228,6 +229,7 @@ export class EditorCtrl {
                 let sepas = msg.data;
                 angular.forEach(sepas, sepa => {
                     sepa.type = 'sepa';
+                    sepa.correspondingUser = this.AuthStatusService.email;
                 });
                 this.allElements["sepa"] = sepas;
                 this.checkForTutorial();
@@ -240,6 +242,7 @@ export class EditorCtrl {
                 let actions = msg.data;
                 angular.forEach(actions, action => {
                     action.type = 'action';
+                    action.correspondingUser = this.AuthStatusService.email;
                 });
                 this.allElements["action"] = actions;
                 this.checkForTutorial();
diff --git a/ui/src/app/notifications/components/notification-item.component.html b/ui/src/app/notifications/components/notification-item.component.html
new file mode 100644
index 0000000..7a31381
--- /dev/null
+++ b/ui/src/app/notifications/components/notification-item.component.html
@@ -0,0 +1,28 @@
+<!--
+  ~   Licensed to the Apache Software Foundation (ASF) under one or more
+  ~   contributor license agreements.  See the NOTICE file distributed with
+  ~   this work for additional information regarding copyright ownership.
+  ~   The ASF licenses this file to You under the Apache License, Version 2.0
+  ~   (the "License"); you may not use this file except in compliance with
+  ~   the License.  You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~   Unless required by applicable law or agreed to in writing, software
+  ~   distributed under the License is distributed on an "AS IS" BASIS,
+  ~   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~   See the License for the specific language governing permissions and
+  ~   limitations under the License.
+  -->
+
+<div class="notification-item">
+    <div class="i">
+        <div class="head">
+            <span class="time">{{notification.createdAt}}</span>
+        </div>
+        <div class="notification-box sp-accent-bg">
+            <div [innerHTML]="sanitizedMessage"></div>
+        </div>
+    </div>
+
+</div>
\ No newline at end of file
diff --git a/ui/src/app/notifications/components/notification-item.component.scss b/ui/src/app/notifications/components/notification-item.component.scss
new file mode 100644
index 0000000..bbb3b92
--- /dev/null
+++ b/ui/src/app/notifications/components/notification-item.component.scss
@@ -0,0 +1,55 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements.  See the NOTICE file distributed with
+ *   this work for additional information regarding copyright ownership.
+ *   The ASF licenses this file to You under the Apache License, Version 2.0
+ *   (the "License"); you may not use this file except in compliance with
+ *   the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ */
+
+@import '../../../scss/_variables';
+
+.head {
+    font-size: 13px;
+}
+.name {
+    font-weight: 600;
+    position: relative;
+}
+
+.time {
+    color: $sp-color-accent;
+}
+.notification-box {
+    margin-top: 20px;
+    color: #fff;
+    font-size: 15px;
+    border-radius: 5px;
+    padding: 20px;
+    line-height: 25px;
+    max-width: 400px;
+    word-wrap: break-word;
+    position: relative;
+}
+.notification-box:before {
+    content: '';
+    position: absolute;
+    width: 0;
+    height: 0;
+    top: -12px;
+    border-bottom: 12px solid #1b1464;
+    border-left: 10px solid transparent;
+    border-right: 10px solid transparent;
+}
+
+.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
new file mode 100644
index 0000000..15d239d
--- /dev/null
+++ b/ui/src/app/notifications/components/notification-item.component.ts
@@ -0,0 +1,39 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements.  See the NOTICE file distributed with
+ *   this work for additional information regarding copyright ownership.
+ *   The ASF licenses this file to You under the Apache License, Version 2.0
+ *   (the "License"); you may not use this file except in compliance with
+ *   the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ */
+
+import {Component, Input, OnInit} from "@angular/core";
+import {NotificationItem} from "../model/notifications.model";
+import {DomSanitizer} from "@angular/platform-browser";
+
+@Component({
+    selector: 'notification-item',
+    templateUrl: './notification-item.component.html',
+    styleUrls: ['./notification-item.component.scss']
+})
+export class NotificationItemComponent implements OnInit {
+
+    @Input() notification: NotificationItem;
+    sanitizedMessage;
+
+    constructor(private domSanitizer: DomSanitizer) {
+
+    }
+
+    ngOnInit(): void {
+        this.sanitizedMessage = this.domSanitizer.bypassSecurityTrustHtml(this.notification.message);
+    }
+}
\ No newline at end of file
diff --git a/ui/src/app/notifications/model/notifications.model.ts b/ui/src/app/notifications/model/notifications.model.ts
new file mode 100644
index 0000000..7d1ce57
--- /dev/null
+++ b/ui/src/app/notifications/model/notifications.model.ts
@@ -0,0 +1,32 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements.  See the NOTICE file distributed with
+ *   this work for additional information regarding copyright ownership.
+ *   The ASF licenses this file to You under the Apache License, Version 2.0
+ *   (the "License"); you may not use this file except in compliance with
+ *   the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ */
+
+export interface NotificationItem {
+    title: string;
+    createdAt: Date;
+    targetedAt: string;
+    correspondingPipelineId: string;
+    message: string;
+    read: boolean;
+}
+
+export interface ExistingNotification {
+    pipelineName: string;
+    notificationTitle: string;
+    pipelineId: string;
+    notificationId: string;
+}
\ No newline at end of file
diff --git a/ui/src/app/notifications/notifications.component.html b/ui/src/app/notifications/notifications.component.html
new file mode 100644
index 0000000..1180323
--- /dev/null
+++ b/ui/src/app/notifications/notifications.component.html
@@ -0,0 +1,67 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxLayout="column" class="page-container page-container-max-height">
+    <div fxLayout="row" style="padding:0px;background-color:#f6f6f6;">
+        <div fxFlex="100" style="line-height:24px;border-bottom:1px solid #ccc">
+            <div fxFlex="100" fxLayout="row">
+                <div fxFlex fxLayoutAlign="start center">
+                    <mat-tab-group>
+                        <mat-tab label="My Notifications"></mat-tab>
+                    </mat-tab-group>
+                </div>
+                <div fxFlex fxLayoutAlign="end center" class="mr-20">
+
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <div class="fixed-height page-container-padding-inner" fxLayout="row" fxFlex="100">
+        <div fxFlex="30" class="notifications-overview scrolling-auto">
+            <mat-list>
+                <mat-list-item *ngFor="let existingNotification of existingNotifications"
+                               (click)="selectNotification(existingNotification)" class="list-item">
+                    <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>
+                    <div class="new-notification-info-panel">
+                        <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" *ngIf="pipelinesWithNotificationsPresent">
+            <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>
+                <div #notificationPane class="notification-pane" (scroll)="onScroll($event)">
+                    <notification-item [notification]="notification" *ngFor="let notification of notifications"></notification-item>
+                </div>
+            </div>
+
+        </div>
+    </div>
+</div>
\ No newline at end of file
diff --git a/ui/src/app/notifications/notifications.component.scss b/ui/src/app/notifications/notifications.component.scss
new file mode 100644
index 0000000..7287acd
--- /dev/null
+++ b/ui/src/app/notifications/notifications.component.scss
@@ -0,0 +1,118 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements.  See the NOTICE file distributed with
+ *   this work for additional information regarding copyright ownership.
+ *   The ASF licenses this file to You under the Apache License, Version 2.0
+ *   (the "License"); you may not use this file except in compliance with
+ *   the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ */
+
+@import '../../scss/_variables';
+
+.fixed-height {
+    flex-direction: row;
+    box-sizing: border-box;
+    display: flex;
+    flex: 1 1 100%;
+    max-height: 100%;
+    overflow-y: auto;
+}
+
+.page-container-max-height {
+    max-height: calc(100% - 20px);
+    //overflow: hidden;
+}
+
+.mr-20 {
+    margin-right:20px;
+}
+
+.notifications-overview {
+    border-right: 5px solid $sp-color-accent;
+}
+
+.notifications-details {
+    padding-top: 20px;
+    display: flex;
+    flex-direction: column;
+    overflow: hidden;
+    flex: 1;
+}
+
+.notification-details-wrapper {
+    display: flex;
+    flex-direction: column;
+    overflow: hidden;
+}
+
+.notification-header {
+    min-height: 75px;
+    padding: 10px 10px 10px 20px;
+    color: $sp-color-accent;
+}
+
+.header-divider {
+    display:flex;
+    align-self: center;
+    margin: 10px 20px;
+    width: 100%;
+    border-top: 2px solid $sp-color-accent
+}
+
+.notification-header-pipeline-name {
+    font-size: 14pt;
+}
+
+.notification-header-notification-name {
+    font-weight: 600;
+}
+
+.notification-avatar {
+    align-items: center;
+    justify-content: center;
+    display: flex;
+    color: white;
+}
+
+.list-item:hover {
+    background: #E0E0E0;
+    cursor: pointer;
+}
+
+.list-item {
+    border-bottom: 1px solid #BDBDBD;
+}
+
+.notification-pane {
+    display: flex;
+    align-items: flex-end;
+    flex-direction: column;
+    overflow-y: auto;
+    padding: 0px 30px 30px 0px;
+    overflow-x: hidden;
+}
+
+.notification-item {
+    margin-bottom: 30px;
+}
+
+.scrolling-auto {
+    overflow: auto;
+    width:100%;
+}
+
+.new-notification-info {
+    background: $sp-color-primary;
+    width: 10px;
+    height: 10px;
+    border-radius: 50%;
+}
+
diff --git a/ui/src/app/notifications/notifications.component.ts b/ui/src/app/notifications/notifications.component.ts
new file mode 100644
index 0000000..7fa96a4
--- /dev/null
+++ b/ui/src/app/notifications/notifications.component.ts
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import {Component, ElementRef, OnInit, ViewChild} from "@angular/core";
+import {RestApi} from "../services/rest-api.service";
+import {NotificationItem, ExistingNotification} from "./model/notifications.model";
+import {ElementIconText} from "../services/get-element-icon-text.service";
+import {NotificationsService} from "./service/notifications.service";
+import {Message} from "@stomp/stompjs";
+import {Subscription} from "rxjs";
+import {RxStompService} from "@stomp/ng2-stompjs";
+import {AuthStatusService} from "../services/auth-status.service";
+import {NotificationUtils} from "./utils/notifications.utils";
+
+@Component({
+    selector: 'notifications',
+    templateUrl: './notifications.component.html',
+    styleUrls: ['./notifications.component.scss']
+})
+export class NotificationsComponent implements OnInit {
+
+    static readonly NOTIFICATIONS_APP_ID = "org.apache.streampipes.sinks.internal.jvm.notification";
+    static readonly NOTIFICATION_TOPIC_PREFIX = "org.apache.streampipes.notifications.";
+    static readonly NOTIFICATION_TITLE_KEY = "title";
+
+    @ViewChild('notificationPane') private notificationContainer: ElementRef;
+
+    notifications: Array<NotificationItem> = [];
+    unreadNotifications: any;
+    existingNotifications: Array<ExistingNotification> = [];
+    currentlySelectedNotification: ExistingNotification;
+    currentlySelectedNotificationId: string;
+
+    pipelinesWithNotificationsPresent: boolean = false;
+    currentOffset: number = 0;
+    previousScrollHeight: number;
+
+    subscription: Subscription;
+    notificationTopic: string;
+
+    newNotificationInfo: Array<boolean> = [];
+
+    constructor(private RestApi: RestApi,
+                private AuthStatusService: AuthStatusService,
+                public elementIconText: ElementIconText,
+                private notificationService: NotificationsService,
+                private rxStompService: RxStompService) {
+        this.notifications = [];
+        this.unreadNotifications = [];
+        this.notificationTopic = NotificationsComponent.NOTIFICATION_TOPIC_PREFIX + AuthStatusService.email;
+    }
+
+    ngOnInit() {
+        this.getPipelinesWithNotifications();
+        this.subscription = this.rxStompService.watch("/topic/" +this.notificationTopic).subscribe((message: Message) => {
+            let notification: NotificationItem = JSON.parse(message.body) as NotificationItem;
+            let notificationId = NotificationUtils.makeNotificationId(notification.correspondingPipelineId, notification.title);
+            if (this.currentlySelectedNotificationId === notificationId) {
+                this.notifications.push(notification);
+            } else {
+                this.newNotificationInfo[notificationId] = true;
+            }
+        });
+    }
+
+    getPipelinesWithNotifications() {
+        this.RestApi.getOwnPipelines().then(pipelines => {
+            this.filterForNotifications(pipelines.data);
+            if (this.existingNotifications.length > 0) {
+                this.pipelinesWithNotificationsPresent = true;
+                this.selectNotification(this.existingNotifications[0]);
+            }
+        });
+    }
+
+    filterForNotifications(pipelines: any) {
+        pipelines.forEach(pipeline => {
+           let notificationActions = pipeline.actions.filter(sink => sink.appId === NotificationsComponent.NOTIFICATIONS_APP_ID);
+             notificationActions.forEach(notificationAction => {
+                let notificationName = notificationAction
+                    .staticProperties
+                    .filter(sp => sp.properties.internalName === NotificationsComponent.NOTIFICATION_TITLE_KEY)
+                    .map(sp => sp.properties.value)[0];
+                let pipelineName = pipeline.name;
+                this.existingNotifications.push({notificationTitle: notificationName,
+                    pipelineName: pipelineName, pipelineId: pipeline._id, notificationId: NotificationUtils.makeNotificationId(pipeline._id, notificationName)});
+             });
+        });
+    }
+
+    getNotifications(notification: ExistingNotification, offset: number, count: number, scrollToBottom: boolean) {
+        this.notificationService.getNotifications(notification, offset, count).subscribe(notifications => {
+            this.notifications.unshift(...notifications);
+            if (scrollToBottom) {
+                setTimeout(() => {
+                    this.notificationContainer.nativeElement.scrollTop = this.notificationContainer.nativeElement.scrollHeight;
+                });
+            } else {
+                setTimeout(() => {
+                    this.notificationContainer.nativeElement.scrollTop = this.notificationContainer.nativeElement.scrollHeight - this.previousScrollHeight;
+                })
+            }
+        })
+    };
+
+    changeNotificationStatus(notificationId) {
+        this.RestApi.updateNotification(notificationId)
+            .then(success => {
+                //this.getNotifications();
+                //this.$rootScope.updateUnreadNotifications();
+            });
+    };
+
+    selectNotification(notification: ExistingNotification) {
+        this.notifications = [];
+        this.currentOffset = 0;
+        this.currentlySelectedNotification = notification;
+        this.currentlySelectedNotificationId = NotificationUtils.makeNotificationIdFromNotification(notification);
+        this.getNotifications(notification, 0, 10, true);
+    }
+
+    onScroll(event: any) {
+        if (this.notificationContainer.nativeElement.scrollTop === 0) {
+            this.currentOffset += 10;
+            this.previousScrollHeight = this.notificationContainer.nativeElement.scrollHeight;
+            this.getNotifications(this.currentlySelectedNotification, this.notifications.length, 10, false);
+        }
+    }
+};
diff --git a/ui/src/app/notifications/notifications.controller.ts b/ui/src/app/notifications/notifications.controller.ts
deleted file mode 100644
index 10ce263..0000000
--- a/ui/src/app/notifications/notifications.controller.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-
-import * as angular from 'angular';
-
-export class NotificationsCtrl {
-
-    RestApi: any;
-    $rootScope: any;
-    notifications: any;
-    unreadNotifications: any;
-
-    constructor(RestApi, $rootScope) {
-        this.RestApi = RestApi;
-        this.$rootScope = $rootScope;
-        this.notifications = [{}];
-        this.unreadNotifications = [];
-    }
-
-    $onInit() {
-        this.getNotifications();
-    }
-
-    getNotifications() {
-        this.unreadNotifications = [];
-        this.RestApi.getNotifications()
-            .then(notifications => {
-                this.notifications = notifications.data;
-                this.getUnreadNotifications();
-            });
-    };
-
-    getUnreadNotifications() {
-        angular.forEach(this.notifications, (value) => {
-            if (!value.read) {
-                this.unreadNotifications.push(value);
-            }
-        });
-    }
-
-    changeNotificationStatus(notificationId) {
-        this.RestApi.updateNotification(notificationId)
-            .then(success => {
-                this.getNotifications();
-                this.$rootScope.updateUnreadNotifications();
-            });
-    };
-};
-
-NotificationsCtrl.$inject = ['RestApi', '$rootScope'];
diff --git a/ui/src/app/notifications/notifications.html b/ui/src/app/notifications/notifications.html
deleted file mode 100644
index c843127..0000000
--- a/ui/src/app/notifications/notifications.html
+++ /dev/null
@@ -1,72 +0,0 @@
-<!--
-  ~ Licensed to the Apache Software Foundation (ASF) under one or more
-  ~ contributor license agreements.  See the NOTICE file distributed with
-  ~ this work for additional information regarding copyright ownership.
-  ~ The ASF licenses this file to You under the Apache License, Version 2.0
-  ~ (the "License"); you may not use this file except in compliance with
-  ~ the License.  You may obtain a copy of the License at
-  ~
-  ~    http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~ Unless required by applicable law or agreed to in writing, software
-  ~ distributed under the License is distributed on an "AS IS" BASIS,
-  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  ~ See the License for the specific language governing permissions and
-  ~ limitations under the License.
-  ~
-  -->
-
-<div flex class="page-container page-container-padding" ng-controller="NotificationsCtrl as ctrl">
-    <div flex="100" layout="row" style="padding:0px;background-color:#f6f6f6">
-    </div>
-    <div flex layout="column" layout-fill>
-        <md-content>
-            <section>
-                <md-subheader class="md-primary">Unread Messages</md-subheader>
-                <md-list layout-padding>
-                    <md-list-item class="md-3-line" ng-repeat="notification in ctrl.unreadNotifications">
-                        <sp-button sp-button-flat class="md-icon-button" ng-click="changeNotificationStatus(notification._id)">
-                            <i class="material-icons" style="color: rgb(63,81,181);">markunread</i>
-                            <md-tooltip md-direction="top">
-                                Mark as unread
-                            </md-tooltip>
-                        </sp-button>
-                        <div class="md-list-item-text" style="margin-bottom:10px;margin-top:10px;">
-                            <h3><b>{{notification.title}}</b></h3>
-                            <div layout="row" layout-align="start center" style="margin-bottom:5px;">
-                                <div layout="row" layout-align="start center"><i class="material-icons" style="color: rgb(63,81,181);">access_time</i>
-                                    &nbsp;{{notification.createdAt | date:'dd.MM.yyyy HH:mm'}}&nbsp;
-                                    <i class="material-icons" style="color: rgb(63,81,181);">person</i>&nbsp;{{notification.targetedUser}}
-                                </div>
-                            </div>
-                            <div class="speech-bubble sp-blue-100-border" ng-bind-html="notification.message">
-                            </div>
-                            <md-divider></md-divider>
-                        </div>
-                    </md-list-item>
-                </md-list>
-            </section>
-            <section>
-                <md-subheader class="md-primary">All Messages</md-subheader>
-                <md-list layout-padding>
-                    <md-list-item class="md-3-line" ng-repeat="notification in ctrl.notifications">
-
-                        <div class="md-list-item-text" style="margin-bottom:10px;margin-top:10px;">
-                            <h3><b>{{notification.title}}</b></h3>
-                            <div layout="row" layout-align="start center" style="margin-bottom:5px;">
-                                <div layout="row" layout-align="start center"><i class="material-icons" style="color: rgb(63,81,181);">access_time</i>
-                                    &nbsp;{{notification.createdAt | date:'dd.MM.yyyy HH:mm'}}&nbsp;
-                                    <i class="material-icons" style="color: rgb(63,81,181);">person</i>&nbsp;{{notification.targetedUser}}
-                                </div>
-                            </div>
-                            <div class="speech-bubble" ng-bind-html="notification.message">
-                            </div>
-                            <md-divider></md-divider>
-                        </div>
-                    </md-list-item>
-                </md-list>
-            </section>
-        </md-content>
-        </md-whiteframe>
-    </div>
-</div>
\ No newline at end of file
diff --git a/ui/src/app/notifications/notifications.module.ts b/ui/src/app/notifications/notifications.module.ts
index a44b8b9..f6175f7 100644
--- a/ui/src/app/notifications/notifications.module.ts
+++ b/ui/src/app/notifications/notifications.module.ts
@@ -16,11 +16,55 @@
  *
  */
 
-import * as angular from 'angular';
+import {NgModule} from "@angular/core";
+import {CommonModule} from "@angular/common";
+import {MatTabsModule} from "@angular/material/tabs";
+import {FlexLayoutModule} from "@angular/flex-layout";
+import {CustomMaterialModule} from "../CustomMaterial/custom-material.module";
+import {FormsModule} from "@angular/forms";
+import {NotificationsComponent} from "./notifications.component";
+import {NotificationItemComponent} from "./components/notification-item.component";
+import {NotificationsService} from "./service/notifications.service";
+import {InjectableRxStompConfig, RxStompService, rxStompServiceFactory} from "@stomp/ng2-stompjs";
 
-import {NotificationsCtrl} from './notifications.controller';
+@NgModule({
+	imports: [
+		CommonModule,
+		MatTabsModule,
+		FlexLayoutModule,
+		CommonModule,
+		FlexLayoutModule,
+		CustomMaterialModule,
+		FormsModule
+	],
+	declarations: [
+		NotificationsComponent,
+		NotificationItemComponent
+	],
+	providers: [
+		NotificationsService,
+		{
+			provide: 'RestApi',
+			useFactory: ($injector: any) => $injector.get('RestApi'),
+			deps: ['$injector'],
+		},
+		{
+			provide: RxStompService,
+			useFactory: rxStompServiceFactory,
+			deps: [InjectableRxStompConfig]
+		},
+	],
+	exports: [
+		NotificationsComponent
+	],
+	entryComponents: [
+		NotificationsComponent,
+	]
+})
+export class NotificationModule {
 
-export default angular.module('sp.notifications', [])
-	.controller('NotificationsCtrl', NotificationsCtrl)
-	.name;
+	constructor() {
+	}
+
+}
 
diff --git a/ui/src/app/notifications/service/notifications.service.ts b/ui/src/app/notifications/service/notifications.service.ts
new file mode 100644
index 0000000..e2d3721
--- /dev/null
+++ b/ui/src/app/notifications/service/notifications.service.ts
@@ -0,0 +1,55 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements.  See the NOTICE file distributed with
+ *   this work for additional information regarding copyright ownership.
+ *   The ASF licenses this file to You under the Apache License, Version 2.0
+ *   (the "License"); you may not use this file except in compliance with
+ *   the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ */
+
+import {HttpClient} from "@angular/common/http";
+import {AuthStatusService} from "../../services/auth-status.service";
+import {Observable} from "rxjs";
+import {ExistingNotification, NotificationItem} from "../model/notifications.model";
+import {Injectable} from "@angular/core";
+import {NotificationUtils} from "../utils/notifications.utils";
+
+@Injectable()
+export class NotificationsService {
+
+    constructor(private http: HttpClient,
+                private authStatusService: AuthStatusService) {
+    }
+
+    getNotifications(existingNotification: ExistingNotification, offset: number, limit: number): Observable<NotificationItem[]> {
+        return this.http
+            .get(this.notificationUrl
+                + "?"
+                + "notificationType=" + NotificationUtils.makeNotificationIdFromNotification(existingNotification)
+                + "&"
+                + "offset=" + offset
+                + "&"
+                + "count=" + limit)
+            .map(data => {
+                return data as NotificationItem[];
+            });
+    }
+
+
+
+    private get baseUrl() {
+        return '/streampipes-backend';
+    }
+
+    private get notificationUrl() {
+        return this.baseUrl + '/api/v2/users/' + this.authStatusService.email + '/notifications'
+    }
+}
\ No newline at end of file
diff --git a/ui/src/app/notifications/utils/notifications.utils.ts b/ui/src/app/notifications/utils/notifications.utils.ts
new file mode 100644
index 0000000..c2ee380
--- /dev/null
+++ b/ui/src/app/notifications/utils/notifications.utils.ts
@@ -0,0 +1,30 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements.  See the NOTICE file distributed with
+ *   this work for additional information regarding copyright ownership.
+ *   The ASF licenses this file to You under the Apache License, Version 2.0
+ *   (the "License"); you may not use this file except in compliance with
+ *   the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ */
+
+import {ExistingNotification} from "../model/notifications.model";
+
+export class NotificationUtils {
+
+    static makeNotificationIdFromNotification(existingNotification: ExistingNotification): string {
+       return this.makeNotificationId(existingNotification.pipelineId, existingNotification.notificationTitle);
+    }
+
+    static makeNotificationId(pipelineId: string, notificationTitle: string) {
+        let vizName = notificationTitle.replace(/\\s/g, '-');
+        return pipelineId + '-' + vizName;
+    }
+}
\ No newline at end of file
diff --git a/ui/src/assets/templates/streampipes.html b/ui/src/assets/templates/streampipes.html
index e76499c..df14e4f 100644
--- a/ui/src/assets/templates/streampipes.html
+++ b/ui/src/assets/templates/streampipes.html
@@ -16,14 +16,12 @@
   ~
   -->
 
-<div ng-controller="ToolbarController as toolbarCtrl">
+<div flex ng-controller="ToolbarController as toolbarCtrl" class="display: flex;min-height: 100vh; max-height: 100vh;">
     <div ui-view="spNavbar"></div>
-    <div layout="row">
-        <div md-whiteframe="6" style="width:40px;height:calc(100vh - 50px);color:white;" class="sp-darkblue"
+    <div style="display: flex;flex-direction: row; height: calc(100vh - 50px);">
+        <div md-whiteframe="6" style="width:40px;color:white;" class="sp-darkblue"
              ui-view="spIconBar"></div>
-        <div flex="100">
             <md-content class="sp-fade-only-enter" id="content" ui-view="spMain"
-                        style="background:#fff !important; height:calc(100vh - 50px);min-height:calc(100vh - 50px)"></md-content>
-        </div>
+                        style="background:#fff !important;flex-grow: 1;"></md-content>
     </div>
 </div>
\ No newline at end of file
diff --git a/ui/src/index.html b/ui/src/index.html
index eafbd4d..8f5eb1e 100644
--- a/ui/src/index.html
+++ b/ui/src/index.html
@@ -106,7 +106,7 @@
 </app-root>
 
 <div layout="column" style="height:100%;" role="main" tabindex="-1" flex>
-    <div class="sp-fade" ui-view="container" flex layout="column" style="min-height: 100vh">
+    <div class="sp-fade" ui-view="container" flex layout="column" style="min-height: 100vh; max-height: 100vh;">
         <div class="app-loading">
             <div class="animated-logo">
                 <img src="/assets/img/favicon/favicon-128.png" class="logo-splash"/>
diff --git a/ui/src/scss/sp/main.scss b/ui/src/scss/sp/main.scss
index 39376a0..e626924 100644
--- a/ui/src/scss/sp/main.scss
+++ b/ui/src/scss/sp/main.scss
@@ -363,7 +363,7 @@ md-content {
   margin: 10px;
   border: 1px solid #cccccc;
   min-height: calc(100% - 20px);
-  height: 100%;
+  //height: 100%;
 }
 
 .page-container-no-border {