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 2021/05/24 21:19:13 UTC
[incubator-streampipes] 02/02: [STREAMPIPES-375] Persist position
of pipeline elements on pipeline canvas
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 bd07903ab31a033934c118b7b13c472429c31fe4
Author: Dominik Riemer <ri...@fzi.de>
AuthorDate: Mon May 24 23:18:58 2021 +0200
[STREAMPIPES-375] Persist position of pipeline elements on pipeline canvas
---
.../backend/StreamPipesResourceConfig.java | 2 +
.../streampipes/model/canvas/CanvasPosition.java | 43 +++++++++
.../model/canvas/PipelineCanvasComment.java | 43 +++++++++
.../model/canvas/PipelineCanvasMetadata.java | 82 ++++++++++++++++
.../model/canvas/PipelineElementMetadata.java | 43 +++++++++
.../rest/impl/AbstractRestResource.java | 10 --
.../rest/impl/PipelineCanvasMetadataCache.java | 54 +++++++++++
.../rest/impl/PipelineCanvasMetadataResource.java | 106 +++++++++++++++++++++
.../streampipes/storage/api/INoSqlStorage.java | 2 +
.../api/IPipelineCanvasMetadataStorage.java | 25 +++++
.../storage/couchdb/CouchDbStorageManager.java | 5 +-
.../impl/PipelineCanvasMetadataStorageImpl.java | 69 ++++++++++++++
.../streampipes/storage/couchdb/utils/Utils.java | 4 +
ui/src/app/core-model/gen/streampipes-model.ts | 75 ++++++++++++++-
.../pipeline-assembly.component.html | 1 +
.../pipeline-assembly.component.ts | 60 +++++++++---
.../components/pipeline/pipeline.component.ts | 48 +++++-----
.../save-pipeline/save-pipeline.component.ts | 30 +++++-
ui/src/app/editor/services/editor.service.ts | 23 ++++-
.../services/pipeline-positioning.service.ts | 76 ++++++++++++---
.../apis/pipeline-canvas-metadata.service.ts | 65 +++++++++++++
ui/src/app/platform-services/platform.module.ts | 2 +
22 files changed, 794 insertions(+), 74 deletions(-)
diff --git a/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesResourceConfig.java b/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesResourceConfig.java
index e6d9521..f2fd784 100644
--- a/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesResourceConfig.java
+++ b/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesResourceConfig.java
@@ -70,6 +70,8 @@ public class StreamPipesResourceConfig extends ResourceConfig {
register(OntologyKnowledge.class);
register(OntologyMeasurementUnit.class);
register(OntologyPipelineElement.class);
+ register(PipelineCanvasMetadataCache.class);
+ register(PipelineCanvasMetadataResource.class);
register(PipelineCache.class);
register(PipelineCategory.class);
register(PipelineElementAsset.class);
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/canvas/CanvasPosition.java b/streampipes-model/src/main/java/org/apache/streampipes/model/canvas/CanvasPosition.java
new file mode 100644
index 0000000..bb94bf2
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/canvas/CanvasPosition.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ *
+ */
+package org.apache.streampipes.model.canvas;
+
+public class CanvasPosition {
+
+ private float x;
+ private float y;
+
+ public CanvasPosition() {
+ }
+
+ public float getX() {
+ return x;
+ }
+
+ public void setX(float x) {
+ this.x = x;
+ }
+
+ public float getY() {
+ return y;
+ }
+
+ public void setY(float y) {
+ this.y = y;
+ }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/canvas/PipelineCanvasComment.java b/streampipes-model/src/main/java/org/apache/streampipes/model/canvas/PipelineCanvasComment.java
new file mode 100644
index 0000000..620e0b6
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/canvas/PipelineCanvasComment.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ *
+ */
+package org.apache.streampipes.model.canvas;
+
+public class PipelineCanvasComment {
+
+ private String comment;
+ private CanvasPosition position;
+
+ public PipelineCanvasComment() {
+ }
+
+ public String getComment() {
+ return comment;
+ }
+
+ public void setComment(String comment) {
+ this.comment = comment;
+ }
+
+ public CanvasPosition getPosition() {
+ return position;
+ }
+
+ public void setPosition(CanvasPosition position) {
+ this.position = position;
+ }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/canvas/PipelineCanvasMetadata.java b/streampipes-model/src/main/java/org/apache/streampipes/model/canvas/PipelineCanvasMetadata.java
new file mode 100644
index 0000000..d22c9be
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/canvas/PipelineCanvasMetadata.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ *
+ */
+package org.apache.streampipes.model.canvas;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.gson.annotations.SerializedName;
+import org.apache.streampipes.model.shared.annotation.TsModel;
+
+import java.util.List;
+import java.util.Map;
+
+@TsModel
+public class PipelineCanvasMetadata {
+
+ @JsonProperty("_id")
+ private @SerializedName("_id") String id;
+
+ @JsonProperty("_rev")
+ private @SerializedName("_rev") String rev;
+
+ private String pipelineId;
+ private Map<String, PipelineElementMetadata> pipelineElementMetadata;
+ private List<PipelineCanvasComment> comments;
+
+ public PipelineCanvasMetadata() {
+ }
+
+ public String getPipelineId() {
+ return pipelineId;
+ }
+
+ public void setPipelineId(String pipelineId) {
+ this.pipelineId = pipelineId;
+ }
+
+ public Map<String, PipelineElementMetadata> getPipelineElementMetadata() {
+ return pipelineElementMetadata;
+ }
+
+ public void setPipelineElementMetadata(Map<String, PipelineElementMetadata> pipelineElementMetadata) {
+ this.pipelineElementMetadata = pipelineElementMetadata;
+ }
+
+ public List<PipelineCanvasComment> getComments() {
+ return comments;
+ }
+
+ public void setComments(List<PipelineCanvasComment> comments) {
+ this.comments = comments;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getRev() {
+ return rev;
+ }
+
+ public void setRev(String rev) {
+ this.rev = rev;
+ }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/canvas/PipelineElementMetadata.java b/streampipes-model/src/main/java/org/apache/streampipes/model/canvas/PipelineElementMetadata.java
new file mode 100644
index 0000000..42012d6
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/canvas/PipelineElementMetadata.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ *
+ */
+package org.apache.streampipes.model.canvas;
+
+public class PipelineElementMetadata {
+
+ private CanvasPosition position;
+ private String customName;
+
+ public PipelineElementMetadata() {
+ }
+
+ public CanvasPosition getPosition() {
+ return position;
+ }
+
+ public void setPosition(CanvasPosition position) {
+ this.position = position;
+ }
+
+ public String getCustomName() {
+ return customName;
+ }
+
+ public void setCustomName(String customName) {
+ this.customName = customName;
+ }
+}
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AbstractRestResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AbstractRestResource.java
index a40ed88..6680401 100644
--- a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AbstractRestResource.java
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/AbstractRestResource.java
@@ -59,16 +59,6 @@ public abstract class AbstractRestResource extends AbstractSharedRestInterface {
}
}
- protected <T> String toJsonLd(String rootElementUri, T object) {
- try {
- return JsonLdUtils.asString(new JsonLdTransformer(rootElementUri).toJsonLd(object));
- } catch (IllegalAccessException | InvocationTargetException | InvalidRdfException | ClassNotFoundException e) {
- return toJson(constructErrorMessage(new Notification(NotificationType.UNKNOWN_ERROR.title(),
- NotificationType.UNKNOWN_ERROR.description(),
- e.getMessage())));
- }
- }
-
protected IPipelineElementDescriptionStorageCache getPipelineElementRdfStorage() {
return StorageManager.INSTANCE.getPipelineElementStorage();
}
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineCanvasMetadataCache.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineCanvasMetadataCache.java
new file mode 100644
index 0000000..83e8b52
--- /dev/null
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineCanvasMetadataCache.java
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ *
+ */
+package org.apache.streampipes.rest.impl;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Path("/v2/users/{username}/pipeline-canvas-cache")
+public class PipelineCanvasMetadataCache extends AbstractRestResource {
+
+ private static ConcurrentHashMap<String, String> cachedCanvasMetadata = new ConcurrentHashMap<>();
+
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response updateCachedCanvasMetadata(@PathParam("username") String user,
+ String canvasMetadata) {
+ cachedCanvasMetadata.put(user, canvasMetadata);
+ return ok();
+ }
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getCachedCanvasMetadata(@PathParam("username") String user) {
+ if (cachedCanvasMetadata.containsKey(user)) {
+ return ok(cachedCanvasMetadata.get(user));
+ } else {
+ return ok();
+ }
+ }
+
+ @DELETE
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response removeCanvasMetadataFromCache(@PathParam("username") String user) {
+ cachedCanvasMetadata.remove(user);
+ return ok();
+ }
+}
diff --git a/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineCanvasMetadataResource.java b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineCanvasMetadataResource.java
new file mode 100644
index 0000000..0aaaa00
--- /dev/null
+++ b/streampipes-rest/src/main/java/org/apache/streampipes/rest/impl/PipelineCanvasMetadataResource.java
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ *
+ */
+package org.apache.streampipes.rest.impl;
+
+import org.apache.streampipes.model.canvas.PipelineCanvasMetadata;
+import org.apache.streampipes.rest.shared.annotation.JacksonSerialized;
+import org.apache.streampipes.storage.api.IPipelineCanvasMetadataStorage;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+@Path("/v2/users/{username}/pipeline-canvas-metadata")
+public class PipelineCanvasMetadataResource extends AbstractRestResource {
+
+ @GET
+ @Path("/pipeline/{pipelineId}")
+ @Produces(MediaType.APPLICATION_JSON)
+ @JacksonSerialized
+ public Response getPipelineCanvasMetadataForPipeline(@PathParam("pipelineId") String pipelineId) {
+ try {
+ return ok(getPipelineCanvasMetadataStorage()
+ .getPipelineCanvasMetadataForPipeline(pipelineId));
+ } catch (IllegalArgumentException e) {
+ return badRequest();
+ }
+ }
+
+ @GET
+ @Path("{canvasId}")
+ @Produces(MediaType.APPLICATION_JSON)
+ @JacksonSerialized
+ public Response getPipelineCanvasMetadata(@PathParam("canvasId") String pipelineCanvasId) {
+ try {
+ return ok(getPipelineCanvasMetadataStorage()
+ .getElementById(pipelineCanvasId));
+ } catch (IllegalArgumentException e) {
+ return badRequest();
+ }
+ }
+
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @JacksonSerialized
+ public Response storePipelineCanvasMetadata(PipelineCanvasMetadata pipelineCanvasMetadata) {
+ getPipelineCanvasMetadataStorage().createElement(pipelineCanvasMetadata);
+ return ok();
+ }
+
+ @DELETE
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("{canvasId}")
+ @JacksonSerialized
+ public Response deletePipelineCanvasMetadata(@PathParam("canvasId") String pipelineCanvasId) {
+ PipelineCanvasMetadata metadata = find(pipelineCanvasId);
+ getPipelineCanvasMetadataStorage().deleteElement(metadata);
+ return ok();
+ }
+
+ @DELETE
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("/pipeline/{pipelineId}")
+ @JacksonSerialized
+ public Response deletePipelineCanvasMetadataForPipeline(@PathParam("pipelineId") String pipelineId) {
+ PipelineCanvasMetadata metadata = getPipelineCanvasMetadataStorage().getPipelineCanvasMetadataForPipeline(pipelineId);
+ getPipelineCanvasMetadataStorage().deleteElement(metadata);
+ return ok();
+ }
+
+ @PUT
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("{canvasId}")
+ @JacksonSerialized
+ public Response updatePipelineCanvasMetadata(@PathParam("canvasId") String pipelineCanvasId,
+ PipelineCanvasMetadata pipelineCanvasMetadata) {
+ try {
+ getPipelineCanvasMetadataStorage().updateElement(pipelineCanvasMetadata);
+ } catch (IllegalArgumentException e) {
+ getPipelineCanvasMetadataStorage().createElement(pipelineCanvasMetadata);
+ }
+ return ok();
+ }
+
+ private PipelineCanvasMetadata find(String canvasId) {
+ return getPipelineCanvasMetadataStorage().getElementById(canvasId);
+ }
+
+ private IPipelineCanvasMetadataStorage getPipelineCanvasMetadataStorage() {
+ return getNoSqlStorage().getPipelineCanvasMetadataStorage();
+ }
+}
diff --git a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java
index 4f1c176..806735b 100644
--- a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java
+++ b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/INoSqlStorage.java
@@ -59,4 +59,6 @@ public interface INoSqlStorage {
IPipelineElementTemplateStorage getPipelineElementTemplateStorage();
+ IPipelineCanvasMetadataStorage getPipelineCanvasMetadataStorage();
+
}
diff --git a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IPipelineCanvasMetadataStorage.java b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IPipelineCanvasMetadataStorage.java
new file mode 100644
index 0000000..fa7c647
--- /dev/null
+++ b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IPipelineCanvasMetadataStorage.java
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ *
+ */
+package org.apache.streampipes.storage.api;
+
+import org.apache.streampipes.model.canvas.PipelineCanvasMetadata;
+
+public interface IPipelineCanvasMetadataStorage extends CRUDStorage<String, PipelineCanvasMetadata> {
+
+ PipelineCanvasMetadata getPipelineCanvasMetadataForPipeline(String pipelineId);
+}
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java
index 1bcd490..dce977f 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/CouchDbStorageManager.java
@@ -120,5 +120,8 @@ public enum CouchDbStorageManager implements INoSqlStorage {
return new PipelineElementTemplateStorageImpl();
}
-
+ @Override
+ public IPipelineCanvasMetadataStorage getPipelineCanvasMetadataStorage() {
+ return new PipelineCanvasMetadataStorageImpl();
+ }
}
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/PipelineCanvasMetadataStorageImpl.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/PipelineCanvasMetadataStorageImpl.java
new file mode 100644
index 0000000..be9f77d
--- /dev/null
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/PipelineCanvasMetadataStorageImpl.java
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ *
+ */
+package org.apache.streampipes.storage.couchdb.impl;
+
+import org.apache.streampipes.model.canvas.PipelineCanvasMetadata;
+import org.apache.streampipes.storage.api.IPipelineCanvasMetadataStorage;
+import org.apache.streampipes.storage.couchdb.dao.AbstractDao;
+import org.apache.streampipes.storage.couchdb.utils.Utils;
+
+import java.util.List;
+
+public class PipelineCanvasMetadataStorageImpl extends AbstractDao<PipelineCanvasMetadata>
+ implements IPipelineCanvasMetadataStorage {
+
+ public PipelineCanvasMetadataStorageImpl() {
+ super(Utils::getCouchDbPipelineCanvasMetadataClient, PipelineCanvasMetadata.class);
+ }
+
+ @Override
+ public List<PipelineCanvasMetadata> getAll() {
+ return findAll();
+ }
+
+ @Override
+ public void createElement(PipelineCanvasMetadata element) {
+ persist(element);
+ }
+
+ @Override
+ public PipelineCanvasMetadata getElementById(String id) {
+ return find(id).orElseThrow(IllegalArgumentException::new);
+ }
+
+ @Override
+ public PipelineCanvasMetadata updateElement(PipelineCanvasMetadata element) {
+ update(element);
+ return find(element.getId()).orElseThrow(IllegalAccessError::new);
+ }
+
+ @Override
+ public void deleteElement(PipelineCanvasMetadata element) {
+ delete(element.getId());
+ }
+
+ @Override
+ public PipelineCanvasMetadata getPipelineCanvasMetadataForPipeline(String pipelineId) {
+ // TODO add CouchDB view
+ return findAll()
+ .stream()
+ .filter(p -> p.getPipelineId().equals(pipelineId))
+ .findFirst()
+ .orElseThrow(IllegalArgumentException::new);
+ }
+}
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/utils/Utils.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/utils/Utils.java
index f81a084..2679d0d 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/utils/Utils.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/utils/Utils.java
@@ -28,6 +28,10 @@ public class Utils {
return getCouchDbGsonClient("pipelineelementtemplate");
}
+ public static CouchDbClient getCouchDbPipelineCanvasMetadataClient() {
+ return getCouchDbGsonClient("pipelinecanvasmetadata");
+ }
+
public static CouchDbClient getCouchDbCategoryClient() {
return getCouchDbGsonClient("category");
}
diff --git a/ui/src/app/core-model/gen/streampipes-model.ts b/ui/src/app/core-model/gen/streampipes-model.ts
index 0fc0532..4fa3957 100644
--- a/ui/src/app/core-model/gen/streampipes-model.ts
+++ b/ui/src/app/core-model/gen/streampipes-model.ts
@@ -16,11 +16,10 @@
*
*/
-
/* tslint:disable */
/* eslint-disable */
// @ts-nocheck
-// Generated using typescript-generator version 2.27.744 on 2021-05-22 23:26:12.
+// Generated using typescript-generator version 2.27.744 on 2021-05-24 18:53:06.
export class AbstractStreamPipesEntity {
"@class": "org.apache.streampipes.model.base.AbstractStreamPipesEntity" | "org.apache.streampipes.model.base.NamedStreamPipesEntity" | "org.apache.streampipes.model.connect.adapter.AdapterDescription" | "org.apache.streampipes.model.connect.adapter.AdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.GenericAdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.SpecificAdapterSetDescription" | "org.apache.streampipes.model.connect.adapter.AdapterStre [...]
@@ -152,8 +151,8 @@ export class NamedStreamPipesEntity extends AbstractStreamPipesEntity {
instance.applicationLinks = __getCopyArrayFn(ApplicationLink.fromData)(data.applicationLinks);
instance.internallyManaged = data.internallyManaged;
instance.connectedTo = __getCopyArrayFn(__identity<string>())(data.connectedTo);
- instance.uri = data.uri;
instance.dom = data.dom;
+ instance.uri = data.uri;
return instance;
}
}
@@ -190,9 +189,9 @@ export class AdapterDescription extends NamedStreamPipesEntity {
instance.rules = __getCopyArrayFn(TransformationRuleDescription.fromDataUnion)(data.rules);
instance.category = __getCopyArrayFn(__identity<string>())(data.category);
instance.createdAt = data.createdAt;
- instance.streamRules = __getCopyArrayFn(__identity<any>())(data.streamRules);
- instance.schemaRules = __getCopyArrayFn(__identity<any>())(data.schemaRules);
instance.valueRules = __getCopyArrayFn(__identity<any>())(data.valueRules);
+ instance.schemaRules = __getCopyArrayFn(__identity<any>())(data.schemaRules);
+ instance.streamRules = __getCopyArrayFn(__identity<any>())(data.streamRules);
instance.couchDBId = data.couchDBId;
instance._rev = data._rev;
return instance;
@@ -601,6 +600,21 @@ export class ApplicationLink extends UnnamedStreamPipesEntity {
}
}
+export class CanvasPosition {
+ x: number;
+ y: number;
+
+ static fromData(data: CanvasPosition, target?: CanvasPosition): CanvasPosition {
+ if (!data) {
+ return data;
+ }
+ const instance = target || new CanvasPosition();
+ instance.x = data.x;
+ instance.y = data.y;
+ return instance;
+ }
+}
+
export class Category {
_id: string;
_rev: string;
@@ -2077,6 +2091,42 @@ export class Pipeline extends ElementComposition {
}
}
+export class PipelineCanvasComment {
+ comment: string;
+ position: CanvasPosition;
+
+ static fromData(data: PipelineCanvasComment, target?: PipelineCanvasComment): PipelineCanvasComment {
+ if (!data) {
+ return data;
+ }
+ const instance = target || new PipelineCanvasComment();
+ instance.comment = data.comment;
+ instance.position = CanvasPosition.fromData(data.position);
+ return instance;
+ }
+}
+
+export class PipelineCanvasMetadata {
+ _id: string;
+ _rev: string;
+ comments: PipelineCanvasComment[];
+ pipelineElementMetadata: { [index: string]: PipelineElementMetadata };
+ pipelineId: string;
+
+ static fromData(data: PipelineCanvasMetadata, target?: PipelineCanvasMetadata): PipelineCanvasMetadata {
+ if (!data) {
+ return data;
+ }
+ const instance = target || new PipelineCanvasMetadata();
+ instance.pipelineId = data.pipelineId;
+ instance.pipelineElementMetadata = __getCopyObjectFn(PipelineElementMetadata.fromData)(data.pipelineElementMetadata);
+ instance.comments = __getCopyArrayFn(PipelineCanvasComment.fromData)(data.comments);
+ instance._id = data._id;
+ instance._rev = data._rev;
+ return instance;
+ }
+}
+
export class PipelineCategory {
_id: string;
_rev: string;
@@ -2096,6 +2146,21 @@ export class PipelineCategory {
}
}
+export class PipelineElementMetadata {
+ customName: string;
+ position: CanvasPosition;
+
+ static fromData(data: PipelineElementMetadata, target?: PipelineElementMetadata): PipelineElementMetadata {
+ if (!data) {
+ return data;
+ }
+ const instance = target || new PipelineElementMetadata();
+ instance.position = CanvasPosition.fromData(data.position);
+ instance.customName = data.customName;
+ return instance;
+ }
+}
+
export class PipelineElementMonitoringInfo {
consumedMessageInfoExists: boolean;
consumedMessagesInfos: ConsumedMessagesInfo[];
diff --git a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.html b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.html
index bf42643..6a616a4 100644
--- a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.html
+++ b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.html
@@ -145,6 +145,7 @@
[allElements]="allElements"
[preview]="false"
[pipelineCached]="pipelineCached"
+ [pipelineCanvasMetadata]="pipelineCanvasMetadata"
[pipelineCacheRunning]="pipelineCacheRunning"
(pipelineCachedChanged)="pipelineCached=$event"
(pipelineCacheRunningChanged)="pipelineCacheRunning=$event">
diff --git a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.ts b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.ts
index e78ee18..ed3c629 100644
--- a/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.ts
+++ b/ui/src/app/editor/components/pipeline-assembly/pipeline-assembly.component.ts
@@ -40,11 +40,13 @@ import {ConfirmDialogComponent} from "../../../core-ui/dialog/confirm-dialog/con
import {MatDialog} from "@angular/material/dialog";
import {EditorService} from "../../services/editor.service";
import {PipelineService} from "../../../platform-services/apis/pipeline.service";
-import {PipelineCanvasScrollingService} from "../../services/pipeline-canvas-scrolling.service";
import {JsplumbFactoryService} from "../../services/jsplumb-factory.service";
import Panzoom, {PanzoomObject} from "@panzoom/panzoom";
import {PipelineElementDraggedService} from "../../services/pipeline-element-dragged.service";
import {PipelineComponent} from "../pipeline/pipeline.component";
+import {PipelineCanvasMetadata} from "../../../core-model/gen/streampipes-model";
+import {forkJoin} from 'rxjs';
+import {PipelineCanvasMetadataService} from "../../../platform-services/apis/pipeline-canvas-metadata.service";
@Component({
@@ -85,6 +87,9 @@ export class PipelineAssemblyComponent implements OnInit {
pipelineCacheRunning: boolean = false;
pipelineCached: boolean = false;
+ pipelineCanvasMetadata: PipelineCanvasMetadata = new PipelineCanvasMetadata();
+ pipelineCanvasMetadataAvailable: boolean = false;
+
config: any = {};
@ViewChild("outerCanvas") pipelineCanvas: ElementRef;
@@ -104,7 +109,8 @@ export class PipelineAssemblyComponent implements OnInit {
private dialogService: DialogService,
private dialog: MatDialog,
private ngZone: NgZone,
- private pipelineElementDraggedService: PipelineElementDraggedService) {
+ private pipelineElementDraggedService: PipelineElementDraggedService,
+ private pipelineCanvasMetadataService: PipelineCanvasMetadataService) {
this.selectMode = true;
this.currentZoomLevel = 1;
@@ -200,7 +206,10 @@ export class PipelineAssemblyComponent implements OnInit {
this.currentZoomLevel = 1;
this.JsplumbBridge.setZoom(this.currentZoomLevel);
this.JsplumbBridge.repaintEverything();
- this.EditorService.removePipelineFromCache().subscribe(msg => {
+
+ let removePipelineFromCache = this.EditorService.removePipelineFromCache();
+ let removeCanvasMetadataFromCache = this.EditorService.removeCanvasMetadataFromCache();
+ forkJoin([removePipelineFromCache, removeCanvasMetadataFromCache]).subscribe(msg => {
this.pipelineCached = false;
this.pipelineCacheRunning = false;
});
@@ -211,7 +220,7 @@ export class PipelineAssemblyComponent implements OnInit {
*/
submit() {
var pipeline = this.ObjectProvider.makeFinalPipeline(this.rawPipelineModel);
-
+ this.PipelinePositioningService.collectPipelineElementPositions(this.pipelineCanvasMetadata, this.rawPipelineModel);
pipeline.name = this.currentPipelineName;
pipeline.description = this.currentPipelineDescription;
if (this.currentModifiedPipelineId) {
@@ -223,34 +232,55 @@ export class PipelineAssemblyComponent implements OnInit {
title: "Save pipeline",
data: {
"pipeline": pipeline,
- "currentModifiedPipelineId": this.currentModifiedPipelineId
+ "currentModifiedPipelineId": this.currentModifiedPipelineId,
+ "pipelineCanvasMetadata": this.pipelineCanvasMetadata
}
});
}
checkAndDisplayCachedPipeline() {
- this.EditorService.getCachedPipeline().subscribe(msg => {
- if (msg) {
- this.rawPipelineModel = msg;
- this.displayPipelineInEditor(true);
+ let cachedPipeline = this.EditorService.getCachedPipeline();
+ let cachedCanvasMetadata = this.EditorService.getCachedPipelineCanvasMetadata();
+ forkJoin([cachedPipeline, cachedCanvasMetadata]).subscribe(results => {
+ if (results[0] && results[0].length > 0) {
+ this.rawPipelineModel = results[0] as PipelineElementConfig[];
+ this.handleCanvasMetadataResponse(results[1]);
+ this.displayPipelineInEditor(!this.pipelineCanvasMetadataAvailable, this.pipelineCanvasMetadata);
}
});
}
displayPipelineById() {
- this.PipelineService.getPipelineById(this.currentModifiedPipelineId)
- .subscribe((msg) => {
- let pipeline = msg;
+ let pipelineRequest = this.PipelineService.getPipelineById(this.currentModifiedPipelineId);
+ let canvasRequest = this.pipelineCanvasMetadataService.getPipelineCanvasMetadata(this.currentModifiedPipelineId);
+ pipelineRequest.subscribe(pipelineResp => {
+ let pipeline = pipelineResp;
this.currentPipelineName = pipeline.name;
this.currentPipelineDescription = pipeline.description;
this.rawPipelineModel = this.JsplumbService.makeRawPipeline(pipeline, false);
- this.displayPipelineInEditor(true);
+ canvasRequest.subscribe(canvasResp => {
+ this.handleCanvasMetadataResponse(canvasResp);
+ }, error => {
+ this.handleCanvasMetadataResponse(undefined);
+ });
});
};
- displayPipelineInEditor(autoLayout) {
+ handleCanvasMetadataResponse(canvasMetadata: PipelineCanvasMetadata) {
+ if (canvasMetadata) {
+ this.pipelineCanvasMetadata = canvasMetadata;
+ this.pipelineCanvasMetadataAvailable = true;
+ } else {
+ this.pipelineCanvasMetadataAvailable = false;
+ this.pipelineCanvasMetadata = new PipelineCanvasMetadata();
+ }
+ this.displayPipelineInEditor(!this.pipelineCanvasMetadataAvailable, this.pipelineCanvasMetadata);
+ }
+
+ displayPipelineInEditor(autoLayout,
+ pipelineCanvasMetadata?: PipelineCanvasMetadata) {
setTimeout(() => {
- this.PipelinePositioningService.displayPipeline(this.rawPipelineModel, "#assembly", false, autoLayout);
+ this.PipelinePositioningService.displayPipeline(this.rawPipelineModel, "#assembly", false, autoLayout, pipelineCanvasMetadata);
this.EditorService.makePipelineAssemblyEmpty(false);
this.ngZone.run(() => {
this.pipelineValid = this.PipelineValidationService
diff --git a/ui/src/app/editor/components/pipeline/pipeline.component.ts b/ui/src/app/editor/components/pipeline/pipeline.component.ts
index c478963..08288fc 100644
--- a/ui/src/app/editor/components/pipeline/pipeline.component.ts
+++ b/ui/src/app/editor/components/pipeline/pipeline.component.ts
@@ -21,15 +21,7 @@ import {JsplumbService} from "../../services/jsplumb.service";
import {PipelineEditorService} from "../../services/pipeline-editor.service";
import {JsplumbBridge} from "../../services/jsplumb-bridge.service";
import {ShepherdService} from "../../../services/tour/shepherd.service";
-import {
- ChangeDetectorRef,
- Component, ElementRef,
- EventEmitter,
- Input,
- NgZone, OnDestroy,
- OnInit,
- Output, ViewChild
-} from "@angular/core";
+import {Component, EventEmitter, Input, NgZone, OnDestroy, OnInit, Output} from "@angular/core";
import {
InvocablePipelineElementUnion,
PipelineElementConfig,
@@ -37,9 +29,13 @@ import {
} from "../../model/editor.model";
import {
CustomOutputStrategy,
- DataProcessorInvocation, DataSinkInvocation, ErrorMessage,
- Pipeline, PipelinePreviewModel, SpDataSet,
- SpDataStream, SpDataStreamUnion
+ DataProcessorInvocation,
+ DataSinkInvocation,
+ Pipeline,
+ PipelineCanvasMetadata,
+ PipelinePreviewModel,
+ SpDataSet,
+ SpDataStream
} from "../../../core-model/gen/streampipes-model";
import {ObjectProvider} from "../../services/object-provider.service";
import {CustomizeComponent} from "../../dialog/customize/customize.component";
@@ -51,10 +47,9 @@ import {MatchingErrorComponent} from "../../dialog/matching-error/matching-error
import {Tuple2} from "../../../core-model/base/Tuple2";
import {ConfirmDialogComponent} from "../../../core-ui/dialog/confirm-dialog/confirm-dialog.component";
import {MatDialog} from "@angular/material/dialog";
-import {Subject} from "rxjs";
-import {PipelineElementDraggedService} from "../../services/pipeline-element-dragged.service";
-import {PipelineCanvasScrollingService} from "../../services/pipeline-canvas-scrolling.service";
+import {forkJoin} from "rxjs";
import {JsplumbFactoryService} from "../../services/jsplumb-factory.service";
+import {PipelinePositioningService} from "../../services/pipeline-positioning.service";
@Component({
selector: 'pipeline',
@@ -87,6 +82,9 @@ export class PipelineComponent implements OnInit, OnDestroy {
@Input()
pipelineCacheRunning: boolean;
+ @Input()
+ pipelineCanvasMetadata: PipelineCanvasMetadata;
+
@Output()
pipelineCacheRunningChanged: EventEmitter<boolean> = new EventEmitter<boolean>();
@@ -109,6 +107,7 @@ export class PipelineComponent implements OnInit, OnDestroy {
constructor(private JsplumbService: JsplumbService,
private PipelineEditorService: PipelineEditorService,
+ private PipelinePositioningService: PipelinePositioningService,
private JsplumbFactoryService: JsplumbFactoryService,
private ObjectProvider: ObjectProvider,
private EditorService: EditorService,
@@ -392,13 +391,18 @@ export class PipelineComponent implements OnInit, OnDestroy {
}
triggerPipelineCacheUpdate() {
- this.pipelineCacheRunning = true;
- this.pipelineCacheRunningChanged.emit(this.pipelineCacheRunning);
- this.EditorService.updateCachedPipeline(this.rawPipelineModel).subscribe(msg => {
- this.pipelineCacheRunning = false;
- this.pipelineCacheRunningChanged.emit(this.pipelineCacheRunning)
- this.pipelineCached = true;
- this.pipelineCachedChanged.emit(this.pipelineCached);
+ setTimeout(() => {
+ this.pipelineCacheRunning = true;
+ this.pipelineCacheRunningChanged.emit(this.pipelineCacheRunning);
+ this.PipelinePositioningService.collectPipelineElementPositions(this.pipelineCanvasMetadata, this.rawPipelineModel);
+ let updateCachedPipeline = this.EditorService.updateCachedPipeline(this.rawPipelineModel);
+ let updateCachedCanvasMetadata = this.EditorService.updateCachedCanvasMetadata(this.pipelineCanvasMetadata);
+ forkJoin([updateCachedPipeline, updateCachedCanvasMetadata]).subscribe(msg => {
+ this.pipelineCacheRunning = false;
+ this.pipelineCacheRunningChanged.emit(this.pipelineCacheRunning)
+ this.pipelineCached = true;
+ this.pipelineCachedChanged.emit(this.pipelineCached);
+ });
});
}
diff --git a/ui/src/app/editor/dialog/save-pipeline/save-pipeline.component.ts b/ui/src/app/editor/dialog/save-pipeline/save-pipeline.component.ts
index 5660ba1..4041746 100644
--- a/ui/src/app/editor/dialog/save-pipeline/save-pipeline.component.ts
+++ b/ui/src/app/editor/dialog/save-pipeline/save-pipeline.component.ts
@@ -18,13 +18,14 @@
import {Component, Input, OnInit} from "@angular/core";
import {DialogRef} from "../../../core-ui/dialog/base-dialog/dialog-ref";
-import {Message, Pipeline} from "../../../core-model/gen/streampipes-model";
+import {Message, Pipeline, PipelineCanvasMetadata} from "../../../core-model/gen/streampipes-model";
import {ObjectProvider} from "../../services/object-provider.service";
import {EditorService} from "../../services/editor.service";
import {PipelineService} from "../../../platform-services/apis/pipeline.service";
import {ShepherdService} from "../../../services/tour/shepherd.service";
import {FormControl, FormGroup, Validators} from "@angular/forms";
import {Router} from "@angular/router";
+import {PipelineCanvasMetadataService} from "../../../platform-services/apis/pipeline-canvas-metadata.service";
@Component({
selector: 'save-pipeline',
@@ -48,20 +49,24 @@ export class SavePipelineComponent implements OnInit {
@Input()
currentModifiedPipelineId: string;
+ @Input()
+ pipelineCanvasMetadata: PipelineCanvasMetadata;
+
saving: boolean = false;
saved: boolean = false;
storageError: boolean = false;
errorMessage: string = '';
- currentPipelineName: string;
+ currentPipelineName: string;
constructor(private editorService: EditorService,
private dialogRef: DialogRef<SavePipelineComponent>,
private objectProvider: ObjectProvider,
private pipelineService: PipelineService,
private Router: Router,
- private ShepherdService: ShepherdService) {
+ private ShepherdService: ShepherdService,
+ private pipelineCanvasService: PipelineCanvasMetadataService) {
this.pipelineCategories = [];
this.updateMode = "update";
}
@@ -112,8 +117,9 @@ export class SavePipelineComponent implements OnInit {
savePipeline(switchTab) {
let storageRequest;
+ let updateMode = this.currentModifiedPipelineId && this.updateMode === 'update';
- if (this.currentModifiedPipelineId && this.updateMode === 'update') {
+ if (updateMode) {
storageRequest = this.pipelineService.updatePipeline(this.pipeline);
} else {
this.pipeline._id = undefined;
@@ -124,6 +130,7 @@ export class SavePipelineComponent implements OnInit {
.subscribe(statusMessage => {
if (statusMessage.success) {
let pipelineId: string = statusMessage.notifications[1].description;
+ this.storePipelineCanvasMetadata(pipelineId, updateMode);
this.afterStorage(statusMessage, switchTab, pipelineId);
} else {
this.displayErrors(statusMessage.notifications[0]);
@@ -133,6 +140,21 @@ export class SavePipelineComponent implements OnInit {
});
};
+ storePipelineCanvasMetadata(pipelineId: string,
+ updateMode: boolean) {
+ let request;
+ this.pipelineCanvasMetadata.pipelineId = pipelineId;
+ if (updateMode) {
+ request = this.pipelineCanvasService.updatePipelineCanvasMetadata(this.pipelineCanvasMetadata);
+ } else {
+ this.pipelineCanvasMetadata._id = undefined;
+ this.pipelineCanvasMetadata._rev = undefined;
+ request = this.pipelineCanvasService.addPipelineCanvasMetadata(this.pipelineCanvasMetadata);
+ }
+
+ request.subscribe();
+ }
+
afterStorage(statusMessage: Message, switchTab, pipelineId?: string) {
this.hide();
this.editorService.makePipelineAssemblyEmpty(true);
diff --git a/ui/src/app/editor/services/editor.service.ts b/ui/src/app/editor/services/editor.service.ts
index 18b115d..a3f244a 100644
--- a/ui/src/app/editor/services/editor.service.ts
+++ b/ui/src/app/editor/services/editor.service.ts
@@ -21,9 +21,12 @@ import {HttpClient} from "@angular/common/http";
import {
DataProcessorInvocation,
DataSetModificationMessage,
- DataSinkInvocation, Pipeline,
+ DataSinkInvocation,
+ Pipeline,
+ PipelineCanvasMetadata,
PipelineElementRecommendationMessage,
- PipelineModificationMessage, PipelinePreviewModel,
+ PipelineModificationMessage,
+ PipelinePreviewModel,
SpDataSet,
SpDataStream
} from "../../core-model/gen/streampipes-model";
@@ -79,6 +82,13 @@ export class EditorService {
}));
}
+ getCachedPipelineCanvasMetadata(): Observable<PipelineCanvasMetadata> {
+ return this.http.get(this.platformServicesCommons.authUserBasePath() + "/pipeline-canvas-cache")
+ .pipe(map(response => {
+ return PipelineCanvasMetadata.fromData(response as any);
+ }));
+ }
+
convert(payload: any) {
if (payload['@class'] === "org.apache.streampipes.model.SpDataSet") {
return SpDataSet.fromData(payload as SpDataSet);
@@ -115,10 +125,19 @@ export class EditorService {
return this.http.post(this.platformServicesCommons.authUserBasePath() + "/pipeline-cache", rawPipelineModel);
}
+ updateCachedCanvasMetadata(pipelineCanvasMetadata: PipelineCanvasMetadata) {
+ return this.http.post(this.platformServicesCommons.authUserBasePath()
+ + "/pipeline-canvas-cache", pipelineCanvasMetadata)
+ }
+
removePipelineFromCache() {
return this.http.delete(this.platformServicesCommons.authUserBasePath() + "/pipeline-cache");
}
+ removeCanvasMetadataFromCache() {
+ return this.http.delete(this.platformServicesCommons.authUserBasePath() + "/pipeline-canvas-cache");
+ }
+
private get pipelinesResourceUrl() {
return this.platformServicesCommons.authUserBasePath() + '/pipelines'
}
diff --git a/ui/src/app/editor/services/pipeline-positioning.service.ts b/ui/src/app/editor/services/pipeline-positioning.service.ts
index ef03614..bf41d28 100644
--- a/ui/src/app/editor/services/pipeline-positioning.service.ts
+++ b/ui/src/app/editor/services/pipeline-positioning.service.ts
@@ -25,6 +25,8 @@ import {PipelineElementConfig} from "../model/editor.model";
import {
DataProcessorInvocation,
DataSinkInvocation,
+ PipelineCanvasMetadata,
+ PipelineElementMetadata,
SpDataStream
} from "../../core-model/gen/streampipes-model";
import {JsplumbFactoryService} from "./jsplumb-factory.service";
@@ -39,10 +41,38 @@ export class PipelinePositioningService {
private ObjectProvider: ObjectProvider) {
}
+ collectPipelineElementPositions(pipelineCanvasMetadata: PipelineCanvasMetadata,
+ rawPipelineModel: PipelineElementConfig[]): PipelineCanvasMetadata {
+ rawPipelineModel.forEach(pe => {
+ this.collectPipelineElementPosition(pe.payload.dom, pipelineCanvasMetadata);
+ });
+ return pipelineCanvasMetadata;
+ }
+
+ collectPipelineElementPosition(domId: string,
+ pipelineCanvasMetadata: PipelineCanvasMetadata) {
+ let elementRef = $(`#${domId}`);
+ if (elementRef && elementRef.position()) {
+ let leftPos = elementRef.position().left;
+ let topPos = elementRef.position().top;
+ if (!pipelineCanvasMetadata.pipelineElementMetadata) {
+ pipelineCanvasMetadata.pipelineElementMetadata = {};
+ }
+ if (!pipelineCanvasMetadata.pipelineElementMetadata[domId]) {
+ pipelineCanvasMetadata.pipelineElementMetadata[domId] = new PipelineElementMetadata();
+ }
+ pipelineCanvasMetadata.pipelineElementMetadata[domId].position = {
+ x: leftPos,
+ y: topPos
+ };
+ }
+ }
+
displayPipeline(rawPipelineModel: PipelineElementConfig[],
targetCanvas,
previewConfig: boolean,
- autoLayout: boolean) {
+ autoLayout: boolean,
+ pipelineCanvasMetadata?: PipelineCanvasMetadata) {
let jsPlumbBridge = this.JsplumbFactoryService.getJsplumbBridge(previewConfig);
let jsplumbConfig = previewConfig ? this.JsplumbConfigService.getPreviewConfig() : this.JsplumbConfigService.getEditorConfig();
rawPipelineModel.forEach(currentPe => {
@@ -65,44 +95,60 @@ export class PipelinePositioningService {
this.connectPipelineElements(rawPipelineModel, previewConfig, jsplumbConfig, jsPlumbBridge);
if (autoLayout) {
this.layoutGraph(targetCanvas, "span[id^='jsplumb']", previewConfig ? 75 : 110, previewConfig);
+ } else if (pipelineCanvasMetadata) {
+ this.layoutGraphFromCanvasMetadata(pipelineCanvasMetadata);
}
jsPlumbBridge.repaintEverything();
}
- layoutGraph(canvas, nodeIdentifier, dimension, isPreview) {
- let jsPlumbBridge = this.JsplumbFactoryService.getJsplumbBridge(isPreview);
- var g = new dagre.graphlib.Graph();
- g.setGraph({rankdir: "LR", ranksep: isPreview ? "50" : "100"});
+ layoutGraph(canvasId: string,
+ nodeIdentifier: string,
+ dimension: number,
+ previewConfig: boolean) {
+ let jsPlumbBridge = this.JsplumbFactoryService.getJsplumbBridge(previewConfig);
+ let g = new dagre.graphlib.Graph();
+ g.setGraph({rankdir: "LR", ranksep: previewConfig ? "50" : "100"});
g.setDefaultEdgeLabel(function () {
return {};
});
- var nodes = $(canvas).find(nodeIdentifier).get();
- nodes.forEach((n, index) => {
+ let nodes = $(canvasId).find(nodeIdentifier).get();
+ nodes.forEach((n) => {
g.setNode(n.id, {label: n.id, width: dimension, height: dimension});
});
- var edges = jsPlumbBridge.getAllConnections();
+ let edges = jsPlumbBridge.getAllConnections();
edges.forEach(edge => {
g.setEdge(edge.source.id, edge.target.id);
});
dagre.layout(g);
g.nodes().forEach(v => {
- $(`#${v}`).css("left", g.node(v).x + "px");
- $(`#${v}`).css("top", g.node(v).y + "px");
+ let elementRef = $(`#${v}`);
+ elementRef.css("left", g.node(v).x + "px");
+ elementRef.css("top", g.node(v).y + "px");
});
}
+ layoutGraphFromCanvasMetadata(pipelineCanvasMetadata: PipelineCanvasMetadata) {
+ Object.entries(pipelineCanvasMetadata.pipelineElementMetadata).forEach(
+ ([key, value]) => {
+ let elementRef = $(`#${key}`);
+ if (elementRef) {
+ elementRef.css("left", value.position.x + "px");
+ elementRef.css("top", value.position.y + "px");
+ }
+ }
+ );
+ }
+
connectPipelineElements(rawPipelineModel: PipelineElementConfig[],
previewConfig: boolean,
jsplumbConfig: any,
jsPlumbBridge: JsplumbBridge) {
- var source, target;
+ let source, target;
jsPlumbBridge.setSuspendDrawing(true);
- for (var i = 0; i < rawPipelineModel.length; i++) {
- var pe = rawPipelineModel[i];
-
+ rawPipelineModel.forEach(pe => {
if (pe.type == "sepa" || pe.type == "action") {
if (!(pe.settings.disabled) && pe.payload.connectedTo) {
pe.payload.connectedTo.forEach((connection, index) => {
@@ -127,7 +173,7 @@ export class PipelinePositioningService {
});
}
}
- }
+ });
jsPlumbBridge.setSuspendDrawing(false, true);
}
}
diff --git a/ui/src/app/platform-services/apis/pipeline-canvas-metadata.service.ts b/ui/src/app/platform-services/apis/pipeline-canvas-metadata.service.ts
new file mode 100644
index 0000000..09d1d5c
--- /dev/null
+++ b/ui/src/app/platform-services/apis/pipeline-canvas-metadata.service.ts
@@ -0,0 +1,65 @@
+/*
+ * 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 {Injectable} from "@angular/core";
+import {HttpClient} from "@angular/common/http";
+import {Observable} from "rxjs";
+import {
+ DataProcessorInvocation,
+ DataSinkInvocation,
+ DataSourceDescription, PipelineCanvasMetadata, SpDataSet, SpDataStream
+} from "../../core-model/gen/streampipes-model";
+import {PlatformServicesCommons} from "./commons.service";
+import {map} from "rxjs/operators";
+
+@Injectable()
+export class PipelineCanvasMetadataService {
+
+ constructor(private http: HttpClient,
+ private platformServicesCommons: PlatformServicesCommons) {
+
+ }
+
+ addPipelineCanvasMetadata(pipelineCanvasMetadata: PipelineCanvasMetadata) {
+ return this.http.post(this.pipelineCanvasMetadataBasePath, pipelineCanvasMetadata);
+ }
+
+ getPipelineCanvasMetadata(pipelineId: string): Observable<PipelineCanvasMetadata> {
+ return this.http.get(this.pipelineCanvasMetadataPipelinePath
+ + pipelineId).pipe(map(response => PipelineCanvasMetadata.fromData(response as any)));
+ }
+
+ updatePipelineCanvasMetadata(pipelineCanvasMetadata: PipelineCanvasMetadata) {
+ return this.http.put(this.pipelineCanvasMetadataBasePath
+ + "/"
+ + pipelineCanvasMetadata.pipelineId, pipelineCanvasMetadata);
+ }
+
+ deletePipelineCanvasMetadata(pipelineId: string) {
+ return this.http.delete(this.pipelineCanvasMetadataPipelinePath
+ + pipelineId);
+ }
+
+ private get pipelineCanvasMetadataBasePath() {
+ return this.platformServicesCommons.authUserBasePath() + "/pipeline-canvas-metadata";
+ }
+
+ private get pipelineCanvasMetadataPipelinePath() {
+ return this.pipelineCanvasMetadataBasePath + "/pipeline/";
+ }
+}
diff --git a/ui/src/app/platform-services/platform.module.ts b/ui/src/app/platform-services/platform.module.ts
index 44c8bea..85800cd 100644
--- a/ui/src/app/platform-services/platform.module.ts
+++ b/ui/src/app/platform-services/platform.module.ts
@@ -26,6 +26,7 @@ import {MeasurementUnitsService} from "./apis/measurement-units.service";
import {PipelineElementTemplateService} from "./apis/pipeline-element-template.service";
import {PipelineMonitoringService} from "./apis/pipeline-monitoring.service";
import {SemanticTypesService} from "./apis/semantic-types.service";
+import {PipelineCanvasMetadataService} from "./apis/pipeline-canvas-metadata.service";
@NgModule({
imports: [],
@@ -34,6 +35,7 @@ import {SemanticTypesService} from "./apis/semantic-types.service";
FilesService,
MeasurementUnitsService,
PlatformServicesCommons,
+ PipelineCanvasMetadataService,
PipelineElementEndpointService,
PipelineElementTemplateService,
//PipelineTemplateService,