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 2022/07/25 15:50:25 UTC

[incubator-streampipes] branch STREAMPIPES-545 updated: [STREAMPIPES-545] Add feature to assign links to asset descriptions

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

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


The following commit(s) were added to refs/heads/STREAMPIPES-545 by this push:
     new 0c2a369e5 [STREAMPIPES-545] Add feature to assign links to asset descriptions
     new 121f90058 Merge branch 'STREAMPIPES-545' of github.com:apache/incubator-streampipes into STREAMPIPES-545
0c2a369e5 is described below

commit 0c2a369e50e484cdaae720ca0c72d1cff0c2afd6
Author: Dominik Riemer <do...@gmail.com>
AuthorDate: Mon Jul 25 17:50:02 2022 +0200

    [STREAMPIPES-545] Add feature to assign links to asset descriptions
---
 .../backend/StreamPipesBackendApplication.java     |   2 +
 .../backend/migrations/AvailableMigrations.java    |  24 ++---
 .../streampipes/backend/migrations/Migration.java  |  11 ++-
 .../backend/migrations/MigrationsHandler.java      |  43 ++++-----
 .../v070/CreateAssetLinkTypeMigration.java         |  49 ++++++++++
 .../v070/CreateDefaultAssetMigration.java          |  45 ++++-----
 .../commons/constants/GenericDocTypes.java         |  10 +-
 .../apache/streampipes/model/assets/AssetLink.java |  62 ++++++++++++
 .../streampipes/model/assets/AssetLinkType.java    | 100 ++++++++++++++++++++
 .../apache/streampipes/model/assets/AssetType.java |  62 ++++++++++++
 .../apache/streampipes/model/assets/SpAsset.java   |  87 +++++++++++++++++
 .../streampipes/model/assets/SpAssetModel.java     |  37 ++++++--
 .../setup/tasks/CreateAssetLinkTypeTask.java       |  60 ++++++++++++
 .../setup/tasks/CreateDefaultAssetTask.java        |  35 ++++---
 .../manager/setup/tasks/InstallationTask.java      |   6 +-
 .../streampipes/storage/api/IGenericStorage.java   |   2 +
 .../storage/couchdb/impl/GenericStorageImpl.java   |   8 ++
 .../src/lib/model/assets/asset.model.ts            |  12 ++-
 ui/src/app/assets/assets.module.ts                 |   4 +
 .../asset-details-panel.component.html             |  35 +++++--
 .../asset-details-panel.component.scss             |  13 +++
 .../asset-details-panel.component.ts               |  76 ++++++++++++++-
 .../asset-link-item/asset-link-item.component.html |  30 ++++++
 .../asset-link-item.component.scss}                |  10 +-
 .../asset-link-item/asset-link-item.component.ts   |  68 ++++++++++++++
 .../asset-details/asset-details.component.html     |  13 ++-
 .../asset-details/asset-details.component.ts       |  39 +++++++-
 .../asset-selection-panel.component.html           |   6 +-
 .../asset-selection-panel.component.scss           |  15 ++-
 .../asset-selection-panel.component.ts             |  27 +++++-
 .../asset-overview/asset-overview.component.html   |  20 ++--
 .../asset-overview/asset-overview.component.ts     |   9 +-
 ui/src/app/assets/constants/asset.constants.ts     |   1 +
 .../edit-asset-link-dialog.component.html          |  76 +++++++++++++++
 .../edit-asset-link-dialog.component.scss}         |   2 +
 .../edit-asset-link-dialog.component.ts            | 104 +++++++++++++++++++++
 36 files changed, 1073 insertions(+), 130 deletions(-)

diff --git a/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesBackendApplication.java b/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesBackendApplication.java
index fb60350c7..f131581e0 100644
--- a/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesBackendApplication.java
+++ b/streampipes-backend/src/main/java/org/apache/streampipes/backend/StreamPipesBackendApplication.java
@@ -17,6 +17,7 @@
  */
 package org.apache.streampipes.backend;
 
+import org.apache.streampipes.backend.migrations.MigrationsHandler;
 import org.apache.streampipes.config.backend.BackendConfig;
 import org.apache.streampipes.manager.health.PipelineHealthCheck;
 import org.apache.streampipes.manager.operations.Operations;
@@ -103,6 +104,7 @@ public class StreamPipesBackendApplication extends StreamPipesServiceBase {
 
     new StreamPipesEnvChecker().updateEnvironmentVariables();
     new CouchDbViewGenerator().createGenericDatabaseIfNotExists();
+    new MigrationsHandler().performMigrations();
 
     executorService.schedule(this::startAllPreviouslyStoppedPipelines, 5, TimeUnit.SECONDS);
     LOG.info("Pipeline health check will run every {} seconds", HEALTH_CHECK_INTERVAL);
diff --git a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/AvailableMigrations.java
similarity index 64%
copy from streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java
copy to streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/AvailableMigrations.java
index 7855a3791..38aa9eda7 100644
--- a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java
+++ b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/AvailableMigrations.java
@@ -16,21 +16,21 @@
  *
  */
 
-package org.apache.streampipes.storage.api;
 
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-public interface IGenericStorage {
+package org.apache.streampipes.backend.migrations;
 
-  List<Map<String, Object>> findAll(String type) throws IOException;
+import org.apache.streampipes.backend.migrations.v070.CreateAssetLinkTypeMigration;
+import org.apache.streampipes.backend.migrations.v070.CreateDefaultAssetMigration;
 
-  Map<String, Object> findOne(String id) throws IOException;
-
-  Map<String, Object> create(String payload) throws IOException;
+import java.util.Arrays;
+import java.util.List;
 
-  Map<String, Object> update(String id, String payload) throws IOException;
+public class AvailableMigrations {
 
-  void delete(String id, String rev) throws IOException;
+  public List<Migration> getAvailableMigrations() {
+    return Arrays.asList(
+      new CreateAssetLinkTypeMigration(),
+      new CreateDefaultAssetMigration()
+    );
+  }
 }
diff --git a/ui/src/app/assets/constants/asset.constants.ts b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/Migration.java
similarity index 83%
copy from ui/src/app/assets/constants/asset.constants.ts
copy to streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/Migration.java
index c0bcb1988..bb165c2b3 100644
--- a/ui/src/app/assets/constants/asset.constants.ts
+++ b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/Migration.java
@@ -16,7 +16,14 @@
  *
  */
 
-export class AssetConstants {
 
-  public static ASSET_APP_DOC_NAME = 'asset-management';
+package org.apache.streampipes.backend.migrations;
+
+public interface Migration {
+
+  boolean shouldExecute();
+
+  void executeMigration();
+
+  String getDescription();
 }
diff --git a/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.scss b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/MigrationsHandler.java
similarity index 55%
copy from ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.scss
copy to streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/MigrationsHandler.java
index 0435c97d6..63f800170 100644
--- a/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.scss
+++ b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/MigrationsHandler.java
@@ -16,38 +16,27 @@
  *
  */
 
-.designer-panel-content {
-  padding: 0;
-  overflow-y: auto;
-}
 
-.designer-panel-config {
-  padding: 0;
-}
+package org.apache.streampipes.backend.migrations;
 
-.designer-panel-title {
-  margin-left: 5px;
-}
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-.designer-panel-header {
-  border-bottom:1px solid var(--color-tab-border);
-}
+public class MigrationsHandler {
 
-.sp-tree-invisible {
-  display: none;
-}
+  private static final Logger LOG = LoggerFactory.getLogger(MigrationsHandler.class);
 
-.sp-tree ul,
-.sp-tree li {
-  margin-top: 0;
-  margin-bottom: 0;
-  list-style-type: none;
-}
+  public void performMigrations() {
+    LOG.info("Checking for required migrations...");
+    var availableMigrations = new AvailableMigrations().getAvailableMigrations();
 
-.sp-tree .mat-nested-tree-node div[role=group] {
-  padding-left: 40px;
-}
+    availableMigrations.forEach(migration -> {
+      if (migration.shouldExecute()) {
+        LOG.info("Performing migration: {}", migration.getDescription());
+        migration.executeMigration();
+      }
+    });
 
-.sp-tree div[role=group] > .mat-tree-node {
-  padding-left: 40px;
+    LOG.info("All migrations completed.");
+  }
 }
diff --git a/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/v070/CreateAssetLinkTypeMigration.java b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/v070/CreateAssetLinkTypeMigration.java
new file mode 100644
index 000000000..27463d980
--- /dev/null
+++ b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/v070/CreateAssetLinkTypeMigration.java
@@ -0,0 +1,49 @@
+/*
+ * 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.backend.migrations.v070;
+
+import org.apache.streampipes.backend.migrations.Migration;
+import org.apache.streampipes.commons.constants.GenericDocTypes;
+import org.apache.streampipes.manager.setup.tasks.CreateAssetLinkTypeTask;
+import org.apache.streampipes.storage.management.StorageDispatcher;
+
+import java.io.IOException;
+
+public class CreateAssetLinkTypeMigration implements Migration {
+
+  @Override
+  public boolean shouldExecute() {
+    try {
+      return StorageDispatcher.INSTANCE.getNoSqlStore().getGenericStorage().findAll(GenericDocTypes.DOC_ASSET_LINK_TYPE).size() == 0;
+    } catch (IOException e) {
+      return true;
+    }
+  }
+
+  @Override
+  public void executeMigration() {
+    new CreateAssetLinkTypeTask().execute();
+  }
+
+  @Override
+  public String getDescription() {
+    return "Populating database with default asset links";
+  }
+}
diff --git a/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.scss b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/v070/CreateDefaultAssetMigration.java
similarity index 55%
copy from ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.scss
copy to streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/v070/CreateDefaultAssetMigration.java
index 0435c97d6..5cedcf4cf 100644
--- a/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.scss
+++ b/streampipes-backend/src/main/java/org/apache/streampipes/backend/migrations/v070/CreateDefaultAssetMigration.java
@@ -16,38 +16,27 @@
  *
  */
 
-.designer-panel-content {
-  padding: 0;
-  overflow-y: auto;
-}
-
-.designer-panel-config {
-  padding: 0;
-}
 
-.designer-panel-title {
-  margin-left: 5px;
-}
+package org.apache.streampipes.backend.migrations.v070;
 
-.designer-panel-header {
-  border-bottom:1px solid var(--color-tab-border);
-}
+import org.apache.streampipes.backend.migrations.Migration;
+import org.apache.streampipes.manager.setup.tasks.CreateDefaultAssetTask;
 
-.sp-tree-invisible {
-  display: none;
-}
+public class CreateDefaultAssetMigration implements Migration {
 
-.sp-tree ul,
-.sp-tree li {
-  margin-top: 0;
-  margin-bottom: 0;
-  list-style-type: none;
-}
+  @Override
+  public boolean shouldExecute() {
+    return true;
+    //return StorageDispatcher.INSTANCE.getNoSqlStore().getGenericStorage().findOne(GenericDocTypes.DEFAULT_ASSET_DOC_ID) == null;
+  }
 
-.sp-tree .mat-nested-tree-node div[role=group] {
-  padding-left: 40px;
-}
+  @Override
+  public void executeMigration() {
+    new CreateDefaultAssetTask().execute();
+  }
 
-.sp-tree div[role=group] > .mat-tree-node {
-  padding-left: 40px;
+  @Override
+  public String getDescription() {
+    return "Creating a default asset representation";
+  }
 }
diff --git a/ui/src/app/assets/constants/asset.constants.ts b/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/GenericDocTypes.java
similarity index 73%
copy from ui/src/app/assets/constants/asset.constants.ts
copy to streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/GenericDocTypes.java
index c0bcb1988..813f06b90 100644
--- a/ui/src/app/assets/constants/asset.constants.ts
+++ b/streampipes-commons/src/main/java/org/apache/streampipes/commons/constants/GenericDocTypes.java
@@ -16,7 +16,13 @@
  *
  */
 
-export class AssetConstants {
+package org.apache.streampipes.commons.constants;
 
-  public static ASSET_APP_DOC_NAME = 'asset-management';
+public class GenericDocTypes {
+
+  public static final String DOC_ASSET_MANGEMENT = "asset-management";
+  public static final String DOC_ASSET_LINK_TYPE = "asset-link-type";
+
+
+  public static final String DEFAULT_ASSET_DOC_ID = "default-asset";
 }
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetLink.java b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetLink.java
new file mode 100644
index 000000000..b04dee4bc
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetLink.java
@@ -0,0 +1,62 @@
+/*
+ * 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.assets;
+
+public class AssetLink {
+
+  private String resourceId;
+  private String linkType;
+  private String linkLabel;
+  private boolean editingDisabled;
+
+  public AssetLink() {
+  }
+
+  public String getResourceId() {
+    return resourceId;
+  }
+
+  public void setResourceId(String resourceId) {
+    this.resourceId = resourceId;
+  }
+
+  public String getLinkType() {
+    return linkType;
+  }
+
+  public void setLinkType(String linkType) {
+    this.linkType = linkType;
+  }
+
+  public String getLinkLabel() {
+    return linkLabel;
+  }
+
+  public void setLinkLabel(String linkLabel) {
+    this.linkLabel = linkLabel;
+  }
+
+  public boolean isEditingDisabled() {
+    return editingDisabled;
+  }
+
+  public void setEditingDisabled(boolean editingDisabled) {
+    this.editingDisabled = editingDisabled;
+  }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetLinkType.java b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetLinkType.java
new file mode 100644
index 000000000..2bb83b6f8
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetLinkType.java
@@ -0,0 +1,100 @@
+/*
+ * 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.assets;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.gson.annotations.SerializedName;
+import org.apache.streampipes.commons.constants.GenericDocTypes;
+
+public class AssetLinkType {
+
+  public final String appDocType = GenericDocTypes.DOC_ASSET_LINK_TYPE;
+
+  @JsonProperty("_id")
+  private @SerializedName("_id") String id;
+
+  private String linkType;
+  private String linkLabel;
+  private String linkColor;
+  private String linkIcon;
+  private String linkQueryHint;
+
+  public AssetLinkType(String linkType, String linkLabel, String linkColor, String linkIcon, String linkQueryHint) {
+    this.linkType = linkType;
+    this.linkLabel = linkLabel;
+    this.linkColor = linkColor;
+    this.linkIcon = linkIcon;
+    this.linkQueryHint = linkQueryHint;
+  }
+
+  public AssetLinkType() {
+  }
+
+  public String getLinkType() {
+    return linkType;
+  }
+
+  public void setLinkType(String linkType) {
+    this.linkType = linkType;
+  }
+
+  public String getLinkLabel() {
+    return linkLabel;
+  }
+
+  public void setLinkLabel(String linkLabel) {
+    this.linkLabel = linkLabel;
+  }
+
+  public String getLinkColor() {
+    return linkColor;
+  }
+
+  public void setLinkColor(String linkColor) {
+    this.linkColor = linkColor;
+  }
+
+  public String getLinkIcon() {
+    return linkIcon;
+  }
+
+  public void setLinkIcon(String linkIcon) {
+    this.linkIcon = linkIcon;
+  }
+
+  public String getLinkQueryHint() {
+    return linkQueryHint;
+  }
+
+  public void setLinkQueryHint(String linkQueryHint) {
+    this.linkQueryHint = linkQueryHint;
+  }
+
+  public String getId() {
+    return id;
+  }
+
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  public String getAppDocType() {
+    return appDocType;
+  }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetType.java b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetType.java
new file mode 100644
index 000000000..45b7151cf
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/AssetType.java
@@ -0,0 +1,62 @@
+/*
+ * 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.assets;
+
+public class AssetType {
+
+  private String assetIcon;
+  private String assetIconColor;
+  private String assetTypeCategory;
+  private String assetTypeLabel;
+
+  public AssetType() {
+  }
+
+  public String getAssetIcon() {
+    return assetIcon;
+  }
+
+  public void setAssetIcon(String assetIcon) {
+    this.assetIcon = assetIcon;
+  }
+
+  public String getAssetIconColor() {
+    return assetIconColor;
+  }
+
+  public void setAssetIconColor(String assetIconColor) {
+    this.assetIconColor = assetIconColor;
+  }
+
+  public String getAssetTypeCategory() {
+    return assetTypeCategory;
+  }
+
+  public void setAssetTypeCategory(String assetTypeCategory) {
+    this.assetTypeCategory = assetTypeCategory;
+  }
+
+  public String getAssetTypeLabel() {
+    return assetTypeLabel;
+  }
+
+  public void setAssetTypeLabel(String assetTypeLabel) {
+    this.assetTypeLabel = assetTypeLabel;
+  }
+}
diff --git a/streampipes-model/src/main/java/org/apache/streampipes/model/assets/SpAsset.java b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/SpAsset.java
new file mode 100644
index 000000000..eeee4c670
--- /dev/null
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/SpAsset.java
@@ -0,0 +1,87 @@
+/*
+ * 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.assets;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SpAsset {
+
+  private String assetId;
+  private String assetName;
+  private String assetDescription;
+
+  private AssetType assetType;
+  private List<AssetLink> assetLinks;
+
+  private List<SpAsset> assets;
+
+  public SpAsset() {
+    this.assets = new ArrayList<>();
+    this.assetLinks = new ArrayList<>();
+  }
+
+  public String getAssetId() {
+    return assetId;
+  }
+
+  public void setAssetId(String assetId) {
+    this.assetId = assetId;
+  }
+
+  public String getAssetName() {
+    return assetName;
+  }
+
+  public void setAssetName(String assetName) {
+    this.assetName = assetName;
+  }
+
+  public String getAssetDescription() {
+    return assetDescription;
+  }
+
+  public void setAssetDescription(String assetDescription) {
+    this.assetDescription = assetDescription;
+  }
+
+  public AssetType getAssetType() {
+    return assetType;
+  }
+
+  public void setAssetType(AssetType assetType) {
+    this.assetType = assetType;
+  }
+
+  public List<AssetLink> getAssetLinks() {
+    return assetLinks;
+  }
+
+  public void setAssetLinks(List<AssetLink> assetLinks) {
+    this.assetLinks = assetLinks;
+  }
+
+  public List<SpAsset> getAssets() {
+    return assets;
+  }
+
+  public void setAssets(List<SpAsset> assets) {
+    this.assets = assets;
+  }
+}
diff --git a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/SpAssetModel.java
similarity index 53%
copy from streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java
copy to streampipes-model/src/main/java/org/apache/streampipes/model/assets/SpAssetModel.java
index 7855a3791..99787aa0b 100644
--- a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java
+++ b/streampipes-model/src/main/java/org/apache/streampipes/model/assets/SpAssetModel.java
@@ -16,21 +16,38 @@
  *
  */
 
-package org.apache.streampipes.storage.api;
+package org.apache.streampipes.model.assets;
 
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.google.gson.annotations.SerializedName;
+import org.apache.streampipes.commons.constants.GenericDocTypes;
 
-public interface IGenericStorage {
+public class SpAssetModel extends SpAsset {
 
-  List<Map<String, Object>> findAll(String type) throws IOException;
+  public static final String appDocType = GenericDocTypes.DOC_ASSET_MANGEMENT;
 
-  Map<String, Object> findOne(String id) throws IOException;
+  @JsonProperty("_id")
+  private @SerializedName("_id") String id;
 
-  Map<String, Object> create(String payload) throws IOException;
+  private boolean removable;
 
-  Map<String, Object> update(String id, String payload) throws IOException;
+  public SpAssetModel() {
+    super();
+  }
 
-  void delete(String id, String rev) throws IOException;
+  public String getId() {
+    return id;
+  }
+
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  public boolean isRemovable() {
+    return removable;
+  }
+
+  public void setRemovable(boolean removable) {
+    this.removable = removable;
+  }
 }
diff --git a/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/tasks/CreateAssetLinkTypeTask.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/tasks/CreateAssetLinkTypeTask.java
new file mode 100644
index 000000000..93ff1c07d
--- /dev/null
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/tasks/CreateAssetLinkTypeTask.java
@@ -0,0 +1,60 @@
+/*
+ * 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.manager.setup.tasks;
+
+import org.apache.streampipes.commons.exceptions.SpRuntimeException;
+import org.apache.streampipes.commons.random.UUIDGenerator;
+import org.apache.streampipes.model.assets.AssetLinkType;
+import org.apache.streampipes.storage.api.IGenericStorage;
+import org.apache.streampipes.storage.management.StorageDispatcher;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+public class CreateAssetLinkTypeTask implements InstallationTask {
+
+  private List<AssetLinkType> defaultLinkTypes = Arrays.asList(
+    new AssetLinkType("data-view", "Data View", "var(--color-data-view)", "search", "data-view"),
+    new AssetLinkType("dashboard", "Dashboard", "var(--color-dashboard)", "insert_chart", "dashboard"),
+    new AssetLinkType("adapter", "Adapter", "var(--color-adapter)", "power", "adapter"),
+    new AssetLinkType("data-source", "Data Source", "var(--color-data-source)", "", "data-source"),
+    new AssetLinkType("pipeline", "Pipeline", "var(--color-pipeline)", "play_arrow", "pipeline"),
+    new AssetLinkType("measurement", "Data Lake Storage", "var(--color-measurement", "", "measurement")
+  );
+
+  @Override
+  public void execute() {
+    var genericStorage = getGenericStorage();
+
+    this.defaultLinkTypes.forEach(link -> {
+      try {
+        link.setId(UUIDGenerator.generateUuid());
+        genericStorage.create(link, AssetLinkType.class);
+      } catch (IOException e) {
+        e.printStackTrace();
+        throw new SpRuntimeException("Could not create asset link document");
+      }
+    });
+  }
+
+  private IGenericStorage getGenericStorage() {
+    return StorageDispatcher.INSTANCE.getNoSqlStore().getGenericStorage();
+  }
+}
diff --git a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/tasks/CreateDefaultAssetTask.java
similarity index 53%
copy from streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java
copy to streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/tasks/CreateDefaultAssetTask.java
index 7855a3791..9293592f6 100644
--- a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/tasks/CreateDefaultAssetTask.java
@@ -16,21 +16,28 @@
  *
  */
 
-package org.apache.streampipes.storage.api;
+package org.apache.streampipes.manager.setup.tasks;
 
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-
-public interface IGenericStorage {
-
-  List<Map<String, Object>> findAll(String type) throws IOException;
+import org.apache.streampipes.commons.constants.GenericDocTypes;
+import org.apache.streampipes.model.assets.SpAssetModel;
+import org.apache.streampipes.storage.management.StorageDispatcher;
 
-  Map<String, Object> findOne(String id) throws IOException;
-
-  Map<String, Object> create(String payload) throws IOException;
-
-  Map<String, Object> update(String id, String payload) throws IOException;
+import java.io.IOException;
 
-  void delete(String id, String rev) throws IOException;
+public class CreateDefaultAssetTask implements InstallationTask {
+
+  @Override
+  public void execute() {
+    var asset = new SpAssetModel();
+    asset.setId(GenericDocTypes.DEFAULT_ASSET_DOC_ID);
+    asset.setAssetId("default-asset");
+    asset.setAssetName("Default Asset");
+    asset.setRemovable(true);
+
+    try {
+      StorageDispatcher.INSTANCE.getNoSqlStore().getGenericStorage().create(asset, SpAssetModel.class);
+    } catch (IOException e) {
+      e.printStackTrace();
+    }
+  }
 }
diff --git a/ui/src/app/assets/constants/asset.constants.ts b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/tasks/InstallationTask.java
similarity index 88%
copy from ui/src/app/assets/constants/asset.constants.ts
copy to streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/tasks/InstallationTask.java
index c0bcb1988..39ec0f1cb 100644
--- a/ui/src/app/assets/constants/asset.constants.ts
+++ b/streampipes-pipeline-management/src/main/java/org/apache/streampipes/manager/setup/tasks/InstallationTask.java
@@ -16,7 +16,9 @@
  *
  */
 
-export class AssetConstants {
+package org.apache.streampipes.manager.setup.tasks;
 
-  public static ASSET_APP_DOC_NAME = 'asset-management';
+public interface InstallationTask {
+
+  void execute();
 }
diff --git a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java
index 7855a3791..b74bbc5b3 100644
--- a/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java
+++ b/streampipes-storage-api/src/main/java/org/apache/streampipes/storage/api/IGenericStorage.java
@@ -30,6 +30,8 @@ public interface IGenericStorage {
 
   Map<String, Object> create(String payload) throws IOException;
 
+  <T> T create(T payload, Class<T> targetClass) throws IOException;
+
   Map<String, Object> update(String id, String payload) throws IOException;
 
   void delete(String id, String rev) throws IOException;
diff --git a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/GenericStorageImpl.java b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/GenericStorageImpl.java
index afa3210b4..27606dd9c 100644
--- a/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/GenericStorageImpl.java
+++ b/streampipes-storage-couchdb/src/main/java/org/apache/streampipes/storage/couchdb/impl/GenericStorageImpl.java
@@ -20,6 +20,7 @@ package org.apache.streampipes.storage.couchdb.impl;
 
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.net.UrlEscapers;
 import org.apache.http.client.fluent.Content;
@@ -44,6 +45,7 @@ public class GenericStorageImpl implements IGenericStorage {
 
   public GenericStorageImpl() {
     this.mapper = new ObjectMapper();
+    this.mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
   }
 
   @Override
@@ -77,6 +79,12 @@ public class GenericStorageImpl implements IGenericStorage {
     return this.findOne((String) requestResult.get(ID));
   }
 
+  @Override
+  public <T> T create(T payload, Class<T> targetClass) throws IOException {
+    Map<String, Object> result = this.create(this.mapper.writeValueAsString(payload));
+    return this.mapper.convertValue(result, targetClass);
+  }
+
   @Override
   public Map<String, Object> update(String id, String payload) throws IOException {
     Request req = Utils.putRequest(getDatabaseRoute() + SLASH + id, payload);
diff --git a/ui/projects/streampipes/platform-services/src/lib/model/assets/asset.model.ts b/ui/projects/streampipes/platform-services/src/lib/model/assets/asset.model.ts
index 59e849dcc..6cb191a10 100644
--- a/ui/projects/streampipes/platform-services/src/lib/model/assets/asset.model.ts
+++ b/ui/projects/streampipes/platform-services/src/lib/model/assets/asset.model.ts
@@ -16,6 +16,14 @@
  *
  */
 
+export interface AssetLinkType {
+  linkType: string;
+  linkLabel: string;
+  linkColor: string;
+  linkIcon?: string;
+  linkQueryHint?: string;
+}
+
 export interface AssetType {
   assetIcon: string;
   assetIconColor: string;
@@ -25,7 +33,7 @@ export interface AssetType {
 
 export interface AssetLink {
   resourceId: string;
-  linkType: 'data-view' | 'dashboard' | 'adapter' | 'stream' | string;
+  linkType: 'data-view' | 'dashboard' | 'adapter' | 'source' | string;
   linkLabel: string;
   editingDisabled: boolean;
 }
@@ -45,6 +53,8 @@ export interface SpAssetModel extends SpAsset {
   _id: string;
   _rev: string;
 
+  appDocType: string;
+
   removable: boolean;
 }
 
diff --git a/ui/src/app/assets/assets.module.ts b/ui/src/app/assets/assets.module.ts
index f66dce7fe..3bcaa5d4c 100644
--- a/ui/src/app/assets/assets.module.ts
+++ b/ui/src/app/assets/assets.module.ts
@@ -40,6 +40,8 @@ import { SpAssetDetailsComponent } from './components/asset-details/asset-detail
 import { SpAssetSelectionPanelComponent } from './components/asset-details/asset-selection-panel/asset-selection-panel.component';
 import { SpAssetDetailsPanelComponent } from './components/asset-details/asset-details-panel/asset-details-panel.component';
 import { MatTreeModule } from '@angular/material/tree';
+import { SpAssetLinkItemComponent } from './components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component';
+import { EditAssetLinkDialogComponent } from './dialog/edit-asset-link/edit-asset-link-dialog.component';
 
 @NgModule({
   imports: [
@@ -84,8 +86,10 @@ import { MatTreeModule } from '@angular/material/tree';
   ],
   declarations: [
     AssetUploadDialogComponent,
+    EditAssetLinkDialogComponent,
     SpAssetDetailsComponent,
     SpAssetDetailsPanelComponent,
+    SpAssetLinkItemComponent,
     SpAssetOverviewComponent,
     SpAssetSelectionPanelComponent,
   ],
diff --git a/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.html b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.html
index c14309519..65beaa635 100644
--- a/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.html
+++ b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.html
@@ -21,18 +21,37 @@
 
     <sp-basic-inner-panel panelTitle="Basics" outerMargin="20px 0px">
         <div fxLayout="column" fxFlex="100">
-            <div>Name: {{asset.assetName}}</div>
-            <div>Description: {{asset.assetDescription}}</div>
+            <mat-form-field color="accent">
+                <mat-label>Name</mat-label>
+                <input matInput [(ngModel)]="asset.assetName" [disabled]="!editMode">
+            </mat-form-field>
+            <mat-form-field color="accent">
+                <mat-label>Description</mat-label>
+                <input matInput [(ngModel)]="asset.assetDescription" [disabled]="!editMode">
+            </mat-form-field>
+            <mat-form-field color="accent">
+                <mat-label>ID</mat-label>
+                <input matInput [(ngModel)]="asset.assetId" [disabled]="!editMode">
+            </mat-form-field>
         </div>
     </sp-basic-inner-panel>
 
 
-    <sp-basic-inner-panel panelTitle="Asset Links" outerMargin="20px 0px">
-        <div fxLayout="column" fxFlex="100">
-            <div fxLayout="column" *ngFor="let link of asset.assetLinks">
-                <div>ResourceId: {{link.resourceId}}</div>
-                <div>Label: {{link.linkLabel}}</div>
-                <div>Link Type: {{link.linkType}}</div>
+    <sp-basic-inner-panel panelTitle="Asset Links" outerMargin="0px 0px">
+        <div header fxLayoutAlign="end center" fxLayout="row" fxFlex="100">
+            <button mat-button color="accent" *ngIf="editMode" (click)="openCreateAssetLinkDialog()"><i class="material-icons">add</i><span>&nbsp;Add link</span></button>
+        </div>
+        <div fxLayout="column" fxFlex="100" *ngIf="assetLinkTypes">
+            <div fxLayout="column" *ngFor="let link of asset.assetLinks; let i = index">
+                <sp-asset-link-item-component [assetLink]="link"
+                                              [assetLinkIndex]="i"
+                                              [assetLinkTypes]="assetLinkTypes"
+                                              [editMode]="editMode"
+                                              (openEditAssetLinkEmitter)="openEditAssetLinkDialog($event.assetLink, $event.index, false)"
+                                              (deleteAssetLinkEmitter)="deleteAssetLink($event)"
+                                              class="asset-link-item">
+                </sp-asset-link-item-component>
+
             </div>
         </div>
     </sp-basic-inner-panel>
diff --git a/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.scss b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.scss
index 13cbc4aac..1dba0de23 100644
--- a/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.scss
+++ b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.scss
@@ -15,3 +15,16 @@
  * limitations under the License.
  *
  */
+
+.asset-link-item:nth-child(odd) {
+  background: var(--color-bg-1);
+}
+
+.asset-link-item:nth-child(even) {
+  background: var(--color-bg-1);
+}
+
+.asset-link-item {
+  border-bottom: 1px solid var(--color-bg-3);
+  padding: 10px;
+}
diff --git a/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.ts b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.ts
index ae668bc2d..d257342ae 100644
--- a/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.ts
+++ b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.ts
@@ -1,5 +1,27 @@
-import { Component, Input, OnInit } from '@angular/core';
-import { SpAsset } from '@streampipes/platform-services';
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { AssetLink, AssetLinkType, GenericStorageService, SpAsset } from '@streampipes/platform-services';
+import { AssetConstants } from '../../../constants/asset.constants';
+import { AssetUploadDialogComponent } from '../../../dialog/asset-upload/asset-upload-dialog.component';
+import { DialogService, PanelType } from '../../../../../../dist/streampipes/shared-ui';
+import { EditAssetLinkDialogComponent } from '../../../dialog/edit-asset-link/edit-asset-link-dialog.component';
 
 
 @Component({
@@ -12,7 +34,57 @@ export class SpAssetDetailsPanelComponent implements OnInit {
   @Input()
   asset: SpAsset;
 
+  @Input()
+  editMode: boolean;
+
+  @Output()
+  updateAssetEmitter: EventEmitter<SpAsset> = new EventEmitter<SpAsset>();
+
+  assetLinkTypes: AssetLinkType[];
+
+  constructor(private genericStorageService: GenericStorageService,
+              private dialogService: DialogService) {
+
+  }
+
   ngOnInit(): void {
+    this.genericStorageService.getAllDocuments(AssetConstants.ASSET_LINK_TYPES_DOC_NAME).subscribe(assetLinkTypes => {
+      this.assetLinkTypes = assetLinkTypes;
+    });
+  }
+
+  openEditAssetLinkDialog(assetLink: AssetLink, index: number, createMode: boolean): void {
+    const dialogRef = this.dialogService.open(EditAssetLinkDialogComponent, {
+      panelType: PanelType.SLIDE_IN_PANEL,
+      title: createMode ? 'Create ' : 'Update ' + 'asset model',
+      width: '50vw',
+      data: {
+        'assetLink': assetLink,
+        'assetLinkTypes': this.assetLinkTypes,
+        'createMode': createMode
+      }
+    });
+
+    dialogRef.afterClosed().subscribe(storedLink => {
+      if (storedLink) {
+        if (index > -1) {
+          this.asset.assetLinks[index] = storedLink;
+        } else {
+          this.asset.assetLinks.push(storedLink);
+        }
+        this.updateAssetEmitter.emit(this.asset);
+      }
+    });
+  }
+
+  openCreateAssetLinkDialog(): void {
+    const assetLink: AssetLink = {linkLabel: '', linkType: 'data-view', editingDisabled: false, resourceId: ''};
+    this.openEditAssetLinkDialog(assetLink, -1, true);
+  }
+
+  deleteAssetLink(index: number): void {
+    this.asset.assetLinks = this.asset.assetLinks.splice(index, 1);
+    this.updateAssetEmitter.emit(this.asset);
   }
 
 }
diff --git a/ui/src/app/assets/components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component.html b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component.html
new file mode 100644
index 000000000..3ca2204c3
--- /dev/null
+++ b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component.html
@@ -0,0 +1,30 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxFlex="100" fxLayout="column">
+    <div fxLayout="row" fxLayoutGap="10px">
+        <div fxLayoutAlign="start center"><span class="link-label">{{assetLink.linkLabel}}</span></div>
+        <div fxLayoutAlign="start center"><span class="link-type" [ngStyle]="{'background': currentAssetLinkType.linkColor}">{{assetLink.linkType}}</span></div>
+        <div fxFlex></div>
+        <div fxLayoutAlign="end center">
+            <button mat-button mat-icon-button color="accent" (click)="openLink()"><i class="material-icons">link</i></button>
+            <button mat-button mat-icon-button color="accent" (click)="editLink()" *ngIf="editMode"><i class="material-icons">edit</i></button>
+            <button mat-button mat-icon-button color="accent" (click)="deleteLink()" *ngIf="editMode"><i class="material-icons">delete</i></button>
+        </div>
+    </div>
+</div>
diff --git a/ui/src/app/assets/constants/asset.constants.ts b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component.scss
similarity index 84%
copy from ui/src/app/assets/constants/asset.constants.ts
copy to ui/src/app/assets/components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component.scss
index c0bcb1988..8e80a29ae 100644
--- a/ui/src/app/assets/constants/asset.constants.ts
+++ b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component.scss
@@ -16,7 +16,13 @@
  *
  */
 
-export class AssetConstants {
+.link-type {
+  background: var(--color-primary);
+  padding: 5px;
+  border-radius: 5px;
+}
 
-  public static ASSET_APP_DOC_NAME = 'asset-management';
+.link-label {
+  margin-right: 15px;
+  font-weight: 500;
 }
diff --git a/ui/src/app/assets/components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component.ts b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component.ts
new file mode 100644
index 000000000..c012491fe
--- /dev/null
+++ b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-link-item/asset-link-item.component.ts
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { AssetLink, AssetLinkType } from '@streampipes/platform-services';
+
+@Component({
+  selector: 'sp-asset-link-item-component',
+  templateUrl: './asset-link-item.component.html',
+  styleUrls: ['./asset-link-item.component.scss']
+})
+export class SpAssetLinkItemComponent implements OnInit {
+
+  @Input()
+  assetLink: AssetLink;
+
+  @Input()
+  assetLinkIndex: number;
+
+  @Input()
+  assetLinkTypes: AssetLinkType[];
+
+  @Input()
+  editMode: boolean;
+
+  @Output()
+  openEditAssetLinkEmitter: EventEmitter<{assetLink: AssetLink, index: number}> = new EventEmitter<{assetLink: AssetLink, index: number}>();
+
+  @Output()
+  deleteAssetLinkEmitter: EventEmitter<number> = new EventEmitter<number>();
+
+  currentAssetLinkType: AssetLinkType;
+
+  ngOnInit(): void {
+    console.log(this.assetLinkTypes);
+    console.log(this.assetLink);
+    this.currentAssetLinkType = this.assetLinkTypes.find(t => t.linkType === this.assetLink.linkType);
+    console.log(this.currentAssetLinkType);
+  }
+
+  openLink(): void {
+
+  }
+
+  editLink(): void {
+    this.openEditAssetLinkEmitter.emit({assetLink: this.assetLink, index: this.assetLinkIndex});
+  }
+
+  deleteLink(): void {
+    this.deleteAssetLinkEmitter.emit(this.assetLinkIndex);
+  }
+}
diff --git a/ui/src/app/assets/components/asset-details/asset-details.component.html b/ui/src/app/assets/components/asset-details/asset-details.component.html
index ce7849c72..4f22df2b4 100644
--- a/ui/src/app/assets/components/asset-details/asset-details.component.html
+++ b/ui/src/app/assets/components/asset-details/asset-details.component.html
@@ -15,10 +15,16 @@
   ~ limitations under the License.
   ~
   -->
-<sp-basic-view [showBackLink]="true" [backLinkTarget]="['assets']" [padding]="false">
+<sp-basic-view [showBackLink]="true"
+               [backLinkTarget]="['assets']"
+               [padding]="false">
 
     <div nav fxFlex="100" fxLayoutAlign="start center" fxLayout="row" class="pl-10">
-
+        <div fxLayout="row" fxLayoutAlign="start center" *ngIf="editMode">
+            <button mat-button mat-raised-button color="accent" (click)="updateAsset()">
+                <i class="material-icons">add</i><span>&nbsp;Save</span>
+            </button>
+        </div>
         <div fxFlex fxLayout="row" fxLayoutAlign="end center">
 
         </div>
@@ -33,6 +39,7 @@
                 <div fxLayout="column" fxFlex="100">
                     <sp-asset-selection-panel-component
                             [assetModel]="asset"
+                            [selectedAsset]="selectedAsset"
                             (selectedAssetEmitter)="selectedAsset = $event">
                     </sp-asset-selection-panel-component>
                 </div>
@@ -41,6 +48,8 @@
                 <sp-asset-details-panel-component
                         *ngIf="selectedAsset"
                         [asset]="selectedAsset"
+                        [editMode]="editMode"
+                        (updateAssetEmitter)="updateAsset()"
                         fxFlex="100"
                         fxLayout="row">
 
diff --git a/ui/src/app/assets/components/asset-details/asset-details.component.ts b/ui/src/app/assets/components/asset-details/asset-details.component.ts
index 7cb5869bd..fc890dd88 100644
--- a/ui/src/app/assets/components/asset-details/asset-details.component.ts
+++ b/ui/src/app/assets/components/asset-details/asset-details.component.ts
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
 import { Component, OnInit } from '@angular/core';
 import { SpBreadcrumbService } from '@streampipes/shared-ui';
 import { ActivatedRoute } from '@angular/router';
@@ -16,6 +34,10 @@ export class SpAssetDetailsComponent implements OnInit {
 
   selectedAsset: SpAsset;
 
+  editMode: boolean;
+
+  assetModelId: string;
+
   constructor(private breadcrumbService: SpBreadcrumbService,
               private genericStorageService: GenericStorageService,
               private route: ActivatedRoute) {
@@ -23,15 +45,22 @@ export class SpAssetDetailsComponent implements OnInit {
   }
 
   ngOnInit(): void {
-    const assetId = this.route.snapshot.params.assetId;
-    this.loadAsset(assetId);
+    this.assetModelId = this.route.snapshot.params.assetId;
+    this.editMode = this.route.snapshot.queryParams.editMode;
+    this.loadAsset();
   }
 
-  loadAsset(assetId: string): void {
-    this.genericStorageService.getDocument(AssetConstants.ASSET_APP_DOC_NAME, assetId).subscribe(asset => {
+  loadAsset(): void {
+    this.genericStorageService.getDocument(AssetConstants.ASSET_APP_DOC_NAME, this.assetModelId).subscribe(asset => {
       this.asset = asset;
+      this.selectedAsset = this.asset;
       this.breadcrumbService.updateBreadcrumb([SpAssetRoutes.BASE, {label: this.asset.assetName}]);
-      console.log(this.asset);
+    });
+  }
+
+  updateAsset() {
+    this.genericStorageService.updateDocument(AssetConstants.ASSET_APP_DOC_NAME, this.asset).subscribe(res => {
+      this.loadAsset();
     });
   }
 }
diff --git a/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.html b/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.html
index 66eb05ca6..096968753 100644
--- a/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.html
+++ b/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.html
@@ -25,9 +25,11 @@
     </div>
     <div fxFlex="100" fxLayout="column">
         <div fxFlex fxLayout="column" class="designer-panel-config">
-            <mat-tree [dataSource]="dataSource" [treeControl]="treeControl" class="sp-tree">
+            <mat-tree [dataSource]="dataSource" [treeControl]="treeControl" class="sp-tree" #tree>
                 <mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle>
+                    <div [ngClass]="node.assetId === selectedAsset.assetId ? 'asset-node selected-node' : 'asset-node'">
                     <span (click)="selectNode(node)">{{node.assetName}}</span>
+                    </div>
                 </mat-tree-node>
                 <mat-nested-tree-node *matTreeNodeDef="let node; when: hasChild">
                     <div class="mat-tree-node">
@@ -38,7 +40,9 @@
                                 {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
                             </mat-icon>
                         </button>
+                        <div [ngClass]="node.assetId === selectedAsset.assetId ? 'asset-node selected-node' : 'asset-node'">
                         <span (click)="selectNode(node)">{{node.assetName}}</span>
+                        </div>
                     </div>
                     <div [class.sp-tree-invisible]="!treeControl.isExpanded(node)"
                          role="group">
diff --git a/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.scss b/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.scss
index 0435c97d6..d277317df 100644
--- a/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.scss
+++ b/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.scss
@@ -45,9 +45,20 @@
 }
 
 .sp-tree .mat-nested-tree-node div[role=group] {
-  padding-left: 40px;
+  padding-left: 20px;
 }
 
 .sp-tree div[role=group] > .mat-tree-node {
-  padding-left: 40px;
+  padding-left: 20px;
+}
+
+.asset-node {
+  font-weight: normal;
+  cursor: pointer;
+  font-size: 13pt;
+}
+
+.selected-node {
+  font-weight: bold;
+  border-bottom: 4px solid var(--color-primary);
 }
diff --git a/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.ts b/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.ts
index ad0c81692..da01568a6 100644
--- a/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.ts
+++ b/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.ts
@@ -1,4 +1,22 @@
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+/*
+ * 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 { AfterViewInit, Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
 import { SpAsset, SpAssetModel } from '@streampipes/platform-services';
 import { NestedTreeControl } from '@angular/cdk/tree';
 import { MatTreeNestedDataSource } from '@angular/material/tree';
@@ -13,18 +31,25 @@ export class SpAssetSelectionPanelComponent implements OnInit {
   @Input()
   assetModel: SpAssetModel;
 
+  @Input()
+  selectedAsset: SpAsset;
+
   @Output()
   selectedAssetEmitter: EventEmitter<SpAsset> = new EventEmitter<SpAsset>();
 
   treeControl = new NestedTreeControl<SpAsset>(node => node.assets);
   dataSource = new MatTreeNestedDataSource<SpAsset>();
 
+  @ViewChild('tree') tree;
+
   hasChild = (_: number, node: SpAsset) => !!node.assets && node.assets.length > 0;
 
   ngOnInit(): void {
     this.treeControl = new NestedTreeControl<SpAsset>(node => node.assets);
     this.dataSource = new MatTreeNestedDataSource<SpAsset>();
     this.dataSource.data = [this.assetModel];
+    this.treeControl.dataNodes = [this.assetModel];
+    this.treeControl.expandAll();
   }
 
   selectNode(asset: SpAsset) {
diff --git a/ui/src/app/assets/components/asset-overview/asset-overview.component.html b/ui/src/app/assets/components/asset-overview/asset-overview.component.html
index 60c86d681..1d7c31e5c 100644
--- a/ui/src/app/assets/components/asset-overview/asset-overview.component.html
+++ b/ui/src/app/assets/components/asset-overview/asset-overview.component.html
@@ -68,18 +68,24 @@
                                 <td mat-cell *matCellDef="let asset">
                                     <div fxLayout="row">
                             <span fxFlex fxFlexOrder="1" fxLayout="row" fxLayoutAlign="center center">
-                    <button color="accent" mat-button mat-icon-button matTooltip="Show info"
-                            matTooltipPosition="above" (click)="goToDetailsView(asset)"><i
-                            class="material-icons">search</i>
-                    </button>
-                        </span>
-                                        <span fxFlex fxFlexOrder="2" fxLayout="row" fxLayoutAlign="center center">
+                                <button color="accent" mat-button mat-icon-button matTooltip="Show info"
+                                        matTooltipPosition="above" (click)="goToDetailsView(asset)"><i
+                                        class="material-icons">search</i>
+                                </button>
+                            </span>
+                            <span fxFlex fxFlexOrder="2" fxLayout="row" fxLayoutAlign="center center">
+                                <button color="accent" mat-button mat-icon-button matTooltip="Show info"
+                                        matTooltipPosition="above" (click)="goToDetailsView(asset, true)"><i
+                                        class="material-icons">edit</i>
+                                </button>
+                            </span>
+                                        <span fxFlex fxFlexOrder="3" fxLayout="row" fxLayoutAlign="center center">
 <!--                    <button color="accent" mat-button mat-icon-button matTooltip="Manage permissions"-->
                                             <!--                            matTooltipPosition="above" (click)="showPermissionsDialog(adapter)"><i-->
                                             <!--                            class="material-icons">share</i>-->
                                             <!--                    </button>-->
                 </span>
-                                        <span fxFlex fxFlexOrder="3" fxLayout="row" fxLayoutAlign="center center">
+                                        <span fxFlex fxFlexOrder="4" fxLayout="row" fxLayoutAlign="center center">
                     <button color="accent" mat-button mat-icon-button matTooltip="Delete adapter"
                             data-cy="delete" matTooltipPosition="above" (click)="deleteAsset(asset)">
                         <i class="material-icons">delete</i>
diff --git a/ui/src/app/assets/components/asset-overview/asset-overview.component.ts b/ui/src/app/assets/components/asset-overview/asset-overview.component.ts
index 225a0a9cd..1d6037ad0 100644
--- a/ui/src/app/assets/components/asset-overview/asset-overview.component.ts
+++ b/ui/src/app/assets/components/asset-overview/asset-overview.component.ts
@@ -75,8 +75,13 @@ export class SpAssetOverviewComponent implements OnInit {
     });
   }
 
-  goToDetailsView(asset: SpAssetModel) {
-    this.router.navigate(['assets', 'details', asset._id]);
+  goToDetailsView(asset: SpAssetModel,
+                  editMode = false) {
+    if (!editMode) {
+      this.router.navigate(['assets', 'details', asset._id]);
+    } else {
+      this.router.navigate(['assets', 'details', asset._id], {queryParams: {'editMode': editMode}});
+    }
   }
 
   deleteAsset(asset: SpAssetModel) {
diff --git a/ui/src/app/assets/constants/asset.constants.ts b/ui/src/app/assets/constants/asset.constants.ts
index c0bcb1988..ee412ee6b 100644
--- a/ui/src/app/assets/constants/asset.constants.ts
+++ b/ui/src/app/assets/constants/asset.constants.ts
@@ -19,4 +19,5 @@
 export class AssetConstants {
 
   public static ASSET_APP_DOC_NAME = 'asset-management';
+  public static ASSET_LINK_TYPES_DOC_NAME = 'asset-link-type';
 }
diff --git a/ui/src/app/assets/dialog/edit-asset-link/edit-asset-link-dialog.component.html b/ui/src/app/assets/dialog/edit-asset-link/edit-asset-link-dialog.component.html
new file mode 100644
index 000000000..5fe1e927c
--- /dev/null
+++ b/ui/src/app/assets/dialog/edit-asset-link/edit-asset-link-dialog.component.html
@@ -0,0 +1,76 @@
+<!--
+~ Licensed to the Apache Software Foundation (ASF) under one or more
+~ contributor license agreements.  See the NOTICE file distributed with
+~ this work for additional information regarding copyright ownership.
+~ The ASF licenses this file to You under the Apache License, Version 2.0
+~ (the "License"); you may not use this file except in compliance with
+~ the License.  You may obtain a copy of the License at
+~
+~    http://www.apache.org/licenses/LICENSE-2.0
+~
+~ Unless required by applicable law or agreed to in writing, software
+~ distributed under the License is distributed on an "AS IS" BASIS,
+~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+~ See the License for the specific language governing permissions and
+~ limitations under the License.
+~
+-->
+
+
+<div class="sp-dialog-container">
+    <div class="sp-dialog-content p-15">
+        <div fxFlex="100" fxLayout="column" *ngIf="clonedAssetLink">
+            <div fxFlex style="margin:5px;width:100%" fxLayout="column">
+                <mat-form-field color="accent">
+                    <mat-label>Link Type</mat-label>
+                    <mat-select fxFlex [(ngModel)]="clonedAssetLink.linkType"
+                                required (selectionChange)="onLinkTypeChanged($event)">
+                        <mat-option *ngFor="let assetLinkType of assetLinkTypes"
+                                    [value]="assetLinkType.linkType">{{assetLinkType.linkLabel}}</mat-option>
+                    </mat-select>
+                </mat-form-field>
+            </div>
+            <div *ngIf="selectedLinkType === 'pipeline'" fxLayout="column">
+                <mat-form-field color="accent" fxFlex="100">
+                    <mat-label>Pipelines</mat-label>
+                    <mat-select [(ngModel)]="clonedAssetLink.resourceId" fxFlex
+                                required>
+                        <mat-option *ngFor="let pipeline of pipelines"
+                                    [value]="pipeline._id">{{pipeline.name}}</mat-option>
+                    </mat-select>
+                </mat-form-field>
+            </div>
+            <div *ngIf="selectedLinkType === 'data-view'" fxLayout="column">
+                <mat-form-field color="accent" fxFlex="100">
+                    <mat-label>Data Views</mat-label>
+                    <mat-select [(ngModel)]="clonedAssetLink.resourceId" fxFlex
+                                required>
+                        <mat-option *ngFor="let dataView of dataViews"
+                                    [value]="dataView._id">{{dataView.name}}</mat-option>
+                    </mat-select>
+                </mat-form-field>
+            </div>
+            <div fxFlex="100" fxLayout="column">
+                <mat-form-field color="accent">
+                    <mat-label>Resource ID</mat-label>
+                    <input matInput [(ngModel)]="clonedAssetLink.resourceId" required [disabled]="true">
+                </mat-form-field>
+            </div>
+            <div fxFlex="100">
+
+            </div>
+        </div>
+    </div>
+    <mat-divider></mat-divider>
+    <div class="sp-dialog-actions">
+        <button mat-button
+                mat-raised-button
+                color="accent"
+                (click)="store()" data-cy="sp-file-management-store-file" style="margin-right:10px;">
+            {{createMode ? 'Create ' : 'Update' }} link
+        </button>
+        <button mat-button mat-raised-button class="mat-basic" (click)="cancel()" style="margin-right:10px;">
+            Cancel
+        </button>
+    </div>
+</div>
diff --git a/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.scss b/ui/src/app/assets/dialog/edit-asset-link/edit-asset-link-dialog.component.scss
similarity index 95%
copy from ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.scss
copy to ui/src/app/assets/dialog/edit-asset-link/edit-asset-link-dialog.component.scss
index 13cbc4aac..704f843e4 100644
--- a/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.scss
+++ b/ui/src/app/assets/dialog/edit-asset-link/edit-asset-link-dialog.component.scss
@@ -15,3 +15,5 @@
  * limitations under the License.
  *
  */
+
+@import 'src/scss/sp/sp-dialog';
diff --git a/ui/src/app/assets/dialog/edit-asset-link/edit-asset-link-dialog.component.ts b/ui/src/app/assets/dialog/edit-asset-link/edit-asset-link-dialog.component.ts
new file mode 100644
index 000000000..e94f3ea0c
--- /dev/null
+++ b/ui/src/app/assets/dialog/edit-asset-link/edit-asset-link-dialog.component.ts
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, Input, OnInit } from '@angular/core';
+import { DialogRef } from '@streampipes/shared-ui';
+import {
+  AssetLink,
+  AssetLinkType, Dashboard, DashboardService,
+  DataViewDataExplorerService,
+  GenericStorageService, Pipeline,
+  PipelineService
+} from '@streampipes/platform-services';
+import { AssetConstants } from '../../constants/asset.constants';
+import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
+import { zip } from 'rxjs';
+import { MatSelectChange } from '@angular/material/select';
+
+@Component({
+  selector: 'sp-edit-asset-link-dialog-component',
+  templateUrl: './edit-asset-link-dialog.component.html',
+  styleUrls: ['./edit-asset-link-dialog.component.scss']
+})
+export class EditAssetLinkDialogComponent implements OnInit {
+
+  @Input()
+  assetLink: AssetLink;
+
+  @Input()
+  assetLinkTypes: AssetLinkType[];
+
+  @Input()
+  createMode: boolean;
+
+  parentForm: FormGroup;
+
+  clonedAssetLink: AssetLink;
+
+  // Resources
+  pipelines: Pipeline[];
+  dataViews: Dashboard[];
+  dashboards: Dashboard[];
+
+  selectedLinkType: string;
+
+  constructor(private dialogRef: DialogRef<EditAssetLinkDialogComponent>,
+              private genericStorageService: GenericStorageService,
+              private pipelineService: PipelineService,
+              private dataViewService: DataViewDataExplorerService,
+              private dashboardService: DashboardService) {
+  }
+
+  ngOnInit(): void {
+    this.getAllResources();
+    this.clonedAssetLink = {...this.assetLink};
+  }
+
+  getCurrAssetLinkType(): AssetLinkType {
+    if (this.createMode) {
+      return this.assetLinkTypes[0];
+    } else {
+      return this.assetLinkTypes.find(a => a.linkType === this.assetLink.linkType);
+    }
+  }
+
+  store() {
+    this.assetLink = this.clonedAssetLink;
+    this.dialogRef.close(this.assetLink);
+  }
+
+  cancel() {
+    this.dialogRef.close();
+  }
+
+  getAllResources() {
+    zip(
+      this.pipelineService.getOwnPipelines(),
+      this.dataViewService.getDataViews(),
+      this.dashboardService.getDashboards()).subscribe(response => {
+      this.pipelines = response[0];
+      this.dataViews = response[1];
+      this.dashboards = response[2];
+    });
+  }
+
+  onLinkTypeChanged(event: MatSelectChange): void {
+    this.selectedLinkType = event.value;
+  }
+
+}