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 <[email protected]> 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,
