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:03 UTC
[incubator-streampipes] 01/03: Refactor NotificationsModule to
Angular 9 module
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>
- {{notification.createdAt | date:'dd.MM.yyyy HH:mm'}}
- <i class="material-icons" style="color: rgb(63,81,181);">person</i> {{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>
- {{notification.createdAt | date:'dd.MM.yyyy HH:mm'}}
- <i class="material-icons" style="color: rgb(63,81,181);">person</i> {{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 {