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/06/15 20:14:04 UTC
[incubator-streampipes] 02/02: [STREAMPIPES-145] Migrate matching
error dialog
This is an automated email from the ASF dual-hosted git repository.
riemer pushed a commit to branch STREAMPIPES-145
in repository https://gitbox.apache.org/repos/asf/incubator-streampipes.git
commit e00001ce2044afdbffbb486e8d85f53ec55824b0
Author: Dominik Riemer <ri...@fzi.de>
AuthorDate: Mon Jun 15 22:13:45 2020 +0200
[STREAMPIPES-145] Migrate matching error dialog
---
.../client/matching/MatchingResultMessage.java | 3 +
.../rest/impl/AbstractRestInterface.java | 46 +++++++--------
.../rest/impl/PipelineWithUserResource.java | 2 +-
.../app/core-model/gen/streampipes-model-client.ts | 57 +++++++++++++++++++
.../standard-dialog/standard-dialog.component.scss | 3 +-
.../components/pipeline/pipeline.component.ts | 46 +++++++++------
.../matching-error/matching-error.component.html | 53 ++++++++++++++++++
.../matching-error/matching-error.component.scss} | 39 +------------
.../matching-error/matching-error.component.ts} | 65 ++++++++++------------
ui/src/app/editor-v2/editor.module.ts | 2 +
10 files changed, 199 insertions(+), 117 deletions(-)
diff --git a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/matching/MatchingResultMessage.java b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/matching/MatchingResultMessage.java
index 7112406..c16ab9c 100644
--- a/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/matching/MatchingResultMessage.java
+++ b/streampipes-model-client/src/main/java/org/apache/streampipes/model/client/matching/MatchingResultMessage.java
@@ -18,6 +18,9 @@
package org.apache.streampipes.model.client.matching;
+import org.apache.streampipes.model.shared.annotation.TsModel;
+
+@TsModel
public class MatchingResultMessage {
private boolean matchingSuccessful;
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AbstractRestInterface.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AbstractRestInterface.java
index 3463064..cdc7913 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AbstractRestInterface.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AbstractRestInterface.java
@@ -18,41 +18,31 @@
package org.apache.streampipes.rest.impl;
+import io.fogsy.empire.core.empire.annotation.InvalidRdfException;
import org.apache.http.client.ClientProtocolException;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
-import org.apache.streampipes.model.base.AbstractStreamPipesEntity;
-import org.apache.streampipes.model.base.StreamPipesJsonLdContainer;
-import org.eclipse.rdf4j.repository.RepositoryException;
-import org.eclipse.rdf4j.rio.RDFHandlerException;
-import org.eclipse.rdf4j.rio.RDFParseException;
-import org.eclipse.rdf4j.rio.UnsupportedRDFormatException;
import org.apache.streampipes.commons.Utils;
-import io.fogsy.empire.core.empire.annotation.InvalidRdfException;
import org.apache.streampipes.manager.endpoint.HttpJsonParser;
import org.apache.streampipes.manager.storage.UserManagementService;
import org.apache.streampipes.manager.storage.UserService;
+import org.apache.streampipes.model.base.AbstractStreamPipesEntity;
import org.apache.streampipes.model.base.NamedStreamPipesEntity;
-import org.apache.streampipes.model.message.ErrorMessage;
-import org.apache.streampipes.model.message.Message;
+import org.apache.streampipes.model.base.StreamPipesJsonLdContainer;
import org.apache.streampipes.model.message.Notification;
-import org.apache.streampipes.model.message.NotificationType;
-import org.apache.streampipes.model.message.SuccessMessage;
+import org.apache.streampipes.model.message.*;
import org.apache.streampipes.serializers.json.GsonSerializer;
import org.apache.streampipes.serializers.jsonld.JsonLdTransformer;
-import org.apache.streampipes.storage.api.IDataLakeStorage;
-import org.apache.streampipes.storage.api.IFileMetadataStorage;
-import org.apache.streampipes.storage.api.INoSqlStorage;
-import org.apache.streampipes.storage.api.INotificationStorage;
-import org.apache.streampipes.storage.api.IPipelineElementDescriptionStorageCache;
-import org.apache.streampipes.storage.api.IPipelineStorage;
-import org.apache.streampipes.storage.api.ITripleStorage;
-import org.apache.streampipes.storage.api.IUserStorage;
-import org.apache.streampipes.storage.api.IVisualizationStorage;
+import org.apache.streampipes.storage.api.*;
import org.apache.streampipes.storage.management.StorageDispatcher;
import org.apache.streampipes.storage.management.StorageManager;
import org.apache.streampipes.storage.rdf4j.util.Transformer;
+import org.eclipse.rdf4j.repository.RepositoryException;
+import org.eclipse.rdf4j.rio.RDFHandlerException;
+import org.eclipse.rdf4j.rio.RDFParseException;
+import org.eclipse.rdf4j.rio.UnsupportedRDFormatException;
+import javax.ws.rs.core.Response;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
@@ -60,8 +50,6 @@ import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.util.List;
-import javax.ws.rs.core.Response;
-
public abstract class AbstractRestInterface {
protected <T> String toJsonLd(T object) {
@@ -150,7 +138,6 @@ public abstract class AbstractRestInterface {
return statusMessage(new ErrorMessage(notifications));
}
-
protected String getCurrentUsername() throws AuthenticationException {
if (SecurityUtils.getSubject().isAuthenticated()) {
return SecurityUtils.getSubject().getPrincipal().toString();
@@ -178,12 +165,25 @@ public abstract class AbstractRestInterface {
.build();
}
+ protected Response statusMessage(Message message, Response.ResponseBuilder builder) {
+ return builder
+ .entity(message)
+ .build();
+ }
+
protected <T> Response ok(T entity) {
return Response
.ok(entity)
.build();
}
+ protected <T> Response badRequest(T entity) {
+ return Response
+ .status(400)
+ .entity(entity)
+ .build();
+ }
+
protected StreamPipesJsonLdContainer asContainer(List<? extends AbstractStreamPipesEntity> elements) {
return new StreamPipesJsonLdContainer(elements);
}
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineWithUserResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineWithUserResource.java
index 4854c69..41ad641 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineWithUserResource.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineWithUserResource.java
@@ -220,7 +220,7 @@ public class PipelineWithUserResource extends AbstractRestInterface implements I
return constructErrorMessage(new Notification(NotificationType.REMOTE_SERVER_NOT_ACCESSIBLE
, e.getMessage()));
} catch (InvalidConnectionException e) {
- return ok(e.getErrorLog());
+ return badRequest(e.getErrorLog());
} catch (Exception e) {
e.printStackTrace();
return constructErrorMessage(new Notification(NotificationType.UNKNOWN_ERROR,
diff --git a/ui/src/app/core-model/gen/streampipes-model-client.ts b/ui/src/app/core-model/gen/streampipes-model-client.ts
new file mode 100644
index 0000000..f36247b
--- /dev/null
+++ b/ui/src/app/core-model/gen/streampipes-model-client.ts
@@ -0,0 +1,57 @@
+/* tslint:disable */
+/* eslint-disable */
+// @ts-nocheck
+// Generated using typescript-generator version 2.23.603 on 2020-06-15 21:49:32.
+
+export class MatchingResultMessage {
+ description: string;
+ matchingSuccessful: boolean;
+ offerSubject: string;
+ reasonText: string;
+ requirementSubject: string;
+ title: string;
+
+ static fromData(data: MatchingResultMessage, target?: MatchingResultMessage): MatchingResultMessage {
+ if (!data) {
+ return data;
+ }
+ const instance = target || new MatchingResultMessage();
+ instance.matchingSuccessful = data.matchingSuccessful;
+ instance.title = data.title;
+ instance.description = data.description;
+ instance.offerSubject = data.offerSubject;
+ instance.requirementSubject = data.requirementSubject;
+ instance.reasonText = data.reasonText;
+ return instance;
+ }
+}
+
+function __getCopyArrayFn<T>(itemCopyFn: (item: T) => T): (array: T[]) => T[] {
+ return (array: T[]) => __copyArray(array, itemCopyFn);
+}
+
+function __copyArray<T>(array: T[], itemCopyFn: (item: T) => T): T[] {
+ return array && array.map(item => item && itemCopyFn(item));
+}
+
+function __getCopyObjectFn<T>(itemCopyFn: (item: T) => T): (object: { [index: string]: T }) => { [index: string]: T } {
+ return (object: { [index: string]: T }) => __copyObject(object, itemCopyFn);
+}
+
+function __copyObject<T>(object: { [index: string]: T }, itemCopyFn: (item: T) => T): { [index: string]: T } {
+ if (!object) {
+ return object;
+ }
+ const result: any = {};
+ for (const key in object) {
+ if (object.hasOwnProperty(key)) {
+ const value = object[key];
+ result[key] = value && itemCopyFn(value);
+ }
+ }
+ return result;
+}
+
+function __identity<T>(): (value: T) => T {
+ return value => value;
+}
diff --git a/ui/src/app/core-ui/dialog/standard-dialog/standard-dialog.component.scss b/ui/src/app/core-ui/dialog/standard-dialog/standard-dialog.component.scss
index 3fe1d06..060041e 100644
--- a/ui/src/app/core-ui/dialog/standard-dialog/standard-dialog.component.scss
+++ b/ui/src/app/core-ui/dialog/standard-dialog/standard-dialog.component.scss
@@ -25,7 +25,8 @@ standard-dialog-container {
}
.dialog-panel {
- height: 80vh;
+ max-height: 80vh;
+ height: 100%;
display: grid;
grid-template-rows: 50px auto;
}
diff --git a/ui/src/app/editor-v2/components/pipeline/pipeline.component.ts b/ui/src/app/editor-v2/components/pipeline/pipeline.component.ts
index e6dd360..edc77ee 100644
--- a/ui/src/app/editor-v2/components/pipeline/pipeline.component.ts
+++ b/ui/src/app/editor-v2/components/pipeline/pipeline.component.ts
@@ -41,6 +41,8 @@ import {CustomizeComponent} from "../../dialog/customize/customize.component";
import {PanelType} from "../../../core-ui/dialog/base-dialog/base-dialog.model";
import {DialogService} from "../../../core-ui/dialog/base-dialog/base-dialog.service";
import {EditorService} from "../../services/editor.service";
+import {MatchingResultMessage} from "../../../core-model/gen/streampipes-model-client";
+import {MatchingErrorComponent} from "../../dialog/matching-error/matching-error.component";
@Component({
selector: 'pipeline',
@@ -296,25 +298,25 @@ export class PipelineComponent implements OnInit {
this.ObjectProvider.updatePipeline(this.currentPipelineModel)
.subscribe(pipelineModificationMessage => {
pe.settings.loadingStatus = false;
- if (pipelineModificationMessage.success) {
- info.targetEndpoint.setType("token");
- this.validatePipeline();
- this.modifyPipeline(pipelineModificationMessage.pipelineModifications);
- var sourceEndpoint = this.JsplumbBridge.selectEndpoints({element: info.targetEndpoint.elementId});
- if (this.PipelineEditorService.isFullyConnected(pe)) {
- let payload = pe.payload as InvocablePipelineElementUnion;
- if ((payload.staticProperties && payload.staticProperties.length > 0) || this.isCustomOutput(pe)) {
- this.showCustomizeDialog(pe);
- } else {
- this.announceConfiguredElement(pe);
- //this.$rootScope.$broadcast("SepaElementConfigured", pe.payload.DOM);
- (pe.payload as InvocablePipelineElementUnion).configured = true;
- }
+ info.targetEndpoint.setType("token");
+ this.validatePipeline();
+ this.modifyPipeline(pipelineModificationMessage.pipelineModifications);
+ var sourceEndpoint = this.JsplumbBridge.selectEndpoints({element: info.targetEndpoint.elementId});
+ if (this.PipelineEditorService.isFullyConnected(pe)) {
+ let payload = pe.payload as InvocablePipelineElementUnion;
+ if ((payload.staticProperties && payload.staticProperties.length > 0) || this.isCustomOutput(pe)) {
+ this.showCustomizeDialog(pe);
+ } else {
+ this.announceConfiguredElement(pe);
+ //this.$rootScope.$broadcast("SepaElementConfigured", pe.payload.DOM);
+ (pe.payload as InvocablePipelineElementUnion).configured = true;
}
- } else {
- this.JsplumbBridge.detach(info.connection);
- this.EditorDialogManager.showMatchingErrorDialog(pipelineModificationMessage);
}
+ }, status => {
+ pe.settings.loadingStatus = false;
+ this.JsplumbBridge.detach(info.connection);
+ let matchingResultMessage = (status.error as any[]).map(e => MatchingResultMessage.fromData(e as MatchingResultMessage));
+ this.showMatchingErrorDialog(matchingResultMessage);
});
}
});
@@ -361,6 +363,16 @@ export class PipelineComponent implements OnInit {
});
}
+ showMatchingErrorDialog(matchingResultMessage: MatchingResultMessage[]) {
+ this.dialogService.open(MatchingErrorComponent, {
+ panelType: PanelType.STANDARD_PANEL,
+ title: "Invalid Connection",
+ data: {
+ "matchingResultMessage": matchingResultMessage
+ }
+ });
+ }
+
showCustomizeDialog(pipelineElement: PipelineElementConfig) {
const dialogRef = this.dialogService.open(CustomizeComponent,{
panelType: PanelType.SLIDE_IN_PANEL,
diff --git a/ui/src/app/editor-v2/dialog/matching-error/matching-error.component.html b/ui/src/app/editor-v2/dialog/matching-error/matching-error.component.html
new file mode 100644
index 0000000..5303852
--- /dev/null
+++ b/ui/src/app/editor-v2/dialog/matching-error/matching-error.component.html
@@ -0,0 +1,53 @@
+<!--
+ ~ 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="sp-dialog-container">
+ <div class="sp-dialog-content p-15">
+ <div>
+ <h4>These elements can't be connected.</h4>
+ <h4>The input data stream does not satisfy the requirements specified by the data processor.</h4>
+ <button mat-button (click)="toggleStatusDetailsVisible()" type="button" class="md-accent">
+ <div *ngIf="!statusDetailsVisible">Show Details</div>
+ <div *ngIf="statusDetailsVisible">Hide Details</div>
+ </button>
+ <div *ngIf="statusDetailsVisible">
+ <div *ngFor="let entry of matchingResultMessage">
+ <div fxFlex="100" class="md-whiteframe-z1" style="margin-bottom:10px;">
+ <div fxFlex fxLayout="column" class="md-padding">
+ <div>
+ <i class="material-icons" *ngIf="entry.matchingResultMessage">done</i>
+ <i class="material-icons" *ngIf="entry.matchingSuccessful">warning</i>
+ <b>{{entry.title}} </b>
+ </div>
+ <div fxFlex="column">
+ {{entry.requirementSubject}}<br/>
+ {{entry.reasonText}}
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <mat-divider></mat-divider>
+ <div class="sp-dialog-actions actions-align-right">
+ <button mat-button mat-raised-button class="mat-basic" (click)="close()">
+ Close
+ </button>
+ </div>
+</div>
\ No newline at end of file
diff --git a/ui/src/app/core-ui/dialog/standard-dialog/standard-dialog.component.scss b/ui/src/app/editor-v2/dialog/matching-error/matching-error.component.scss
similarity index 58%
copy from ui/src/app/core-ui/dialog/standard-dialog/standard-dialog.component.scss
copy to ui/src/app/editor-v2/dialog/matching-error/matching-error.component.scss
index 3fe1d06..0a776e5 100644
--- a/ui/src/app/core-ui/dialog/standard-dialog/standard-dialog.component.scss
+++ b/ui/src/app/editor-v2/dialog/matching-error/matching-error.component.scss
@@ -16,41 +16,4 @@
*
*/
-@import 'src/scss/sp/colors';
-
-standard-dialog-container {
- width: 100%;
- background-color: #fff;
- box-shadow: -7px 0px 5px -5px #5d5d5d;
-}
-
-.dialog-panel {
- height: 80vh;
- display: grid;
- grid-template-rows: 50px auto;
-}
-
-.dialog-panel-header {
- display: flex;
- justify-content: space-between;
- height: 50px;
- min-height: 50px;
- width: 100%;
- background: $sp-color-accent;
- align-items: center;
-}
-
-.dialog-panel-content {
- height: 100%;
- overflow-y:auto;
-}
-
-.dialog-title {
- padding: 5px 5px 5px 15px;
- font-size:25px;
- color: white;
-}
-
-#portal {
- width:100%;
-}
\ No newline at end of file
+@import '../../../../scss/sp/sp-dialog.scss';
\ No newline at end of file
diff --git a/ui/src/app/core-ui/dialog/standard-dialog/standard-dialog.component.scss b/ui/src/app/editor-v2/dialog/matching-error/matching-error.component.ts
similarity index 53%
copy from ui/src/app/core-ui/dialog/standard-dialog/standard-dialog.component.scss
copy to ui/src/app/editor-v2/dialog/matching-error/matching-error.component.ts
index 3fe1d06..ac21a03 100644
--- a/ui/src/app/core-ui/dialog/standard-dialog/standard-dialog.component.scss
+++ b/ui/src/app/editor-v2/dialog/matching-error/matching-error.component.ts
@@ -16,41 +16,32 @@
*
*/
-@import 'src/scss/sp/colors';
-
-standard-dialog-container {
- width: 100%;
- background-color: #fff;
- box-shadow: -7px 0px 5px -5px #5d5d5d;
-}
-
-.dialog-panel {
- height: 80vh;
- display: grid;
- grid-template-rows: 50px auto;
-}
-
-.dialog-panel-header {
- display: flex;
- justify-content: space-between;
- height: 50px;
- min-height: 50px;
- width: 100%;
- background: $sp-color-accent;
- align-items: center;
-}
-
-.dialog-panel-content {
- height: 100%;
- overflow-y:auto;
-}
-
-.dialog-title {
- padding: 5px 5px 5px 15px;
- font-size:25px;
- color: white;
-}
-
-#portal {
- width:100%;
+import {Component, Input} from "@angular/core";
+import {DialogRef} from "../../../core-ui/dialog/base-dialog/dialog-ref";
+import {MatchingResultMessage} from "../../../core-model/gen/streampipes-model-client";
+
+@Component({
+ selector: 'matching-error',
+ templateUrl: './matching-error.component.html',
+ styleUrls: ['./matching-error.component.scss']
+})
+export class MatchingErrorComponent {
+
+ @Input()
+ matchingResultMessage: MatchingResultMessage[];
+
+ msg: any;
+ statusDetailsVisible: any;
+
+ constructor(private DialogRef: DialogRef<MatchingErrorComponent>) {
+
+ }
+
+ close() {
+ this.DialogRef.close();
+ };
+
+ toggleStatusDetailsVisible() {
+ this.statusDetailsVisible = !(this.statusDetailsVisible);
+ }
}
\ No newline at end of file
diff --git a/ui/src/app/editor-v2/editor.module.ts b/ui/src/app/editor-v2/editor.module.ts
index d363f43..9d82380 100644
--- a/ui/src/app/editor-v2/editor.module.ts
+++ b/ui/src/app/editor-v2/editor.module.ts
@@ -56,6 +56,7 @@ import {HelpComponent} from "./dialog/help/help.component";
import {PipelineElementDocumentationComponent} from "./components/pipeline-element-documentation/pipeline-element-documentation.component";
import { ShowdownModule } from 'ngx-showdown';
import {SafeCss} from "./utils/style-sanitizer";
+import {MatchingErrorComponent} from "./dialog/matching-error/matching-error.component";
@NgModule({
imports: [
@@ -78,6 +79,7 @@ import {SafeCss} from "./utils/style-sanitizer";
CustomizeComponent,
EditorComponent,
HelpComponent,
+ MatchingErrorComponent,
PipelineAssemblyComponent,
PipelineElementComponent,
PipelineElementDocumentationComponent,