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/18 20:18:58 UTC

[incubator-streampipes] 01/01: [STREAMPIPES-545] Add initial view for managing assets

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

commit f4b2fad56ec7a6362c0cd6b4f2d3a028c227ec21
Author: Dominik Riemer <do...@gmail.com>
AuthorDate: Mon Jul 18 22:18:43 2022 +0200

    [STREAMPIPES-545] Add initial view for managing assets
---
 ui/deployment/dev/config.yml                       |   1 +
 ui/deployment/modules.yml                          |  15 +++
 .../src/lib/model/assets/asset.model.ts            |  37 ++++---
 ui/src/app/_enums/page-name.enum.ts                |   1 +
 ui/src/app/assets/assets.module.ts                 |  94 +++++++++++++++++
 .../page-name.enum.ts => assets/assets.routes.ts}  |  21 ++--
 .../asset-details-panel.component.html             |  39 +++++++
 .../asset-details-panel.component.scss}            |  16 ---
 .../asset-details-panel.component.ts               |  18 ++++
 .../asset-details/asset-details.component.html     |  51 ++++++++++
 .../asset-details/asset-details.component.scss}    |  27 +++--
 .../asset-details/asset-details.component.ts       |  37 +++++++
 .../asset-selection-panel.component.html           |  51 ++++++++++
 .../asset-selection-panel.component.scss}          |  48 +++++----
 .../asset-selection-panel.component.ts             |  35 +++++++
 .../asset-overview/asset-overview.component.html   | 113 +++++++++++++++++++++
 .../asset-overview/asset-overview.component.scss}  |  16 +--
 .../asset-overview/asset-overview.component.ts     |  93 +++++++++++++++++
 .../constants/asset.constants.ts}                  |  17 +---
 .../asset-upload-dialog.component.html             |  68 +++++++++++++
 .../asset-upload-dialog.component.scss}            |  16 +--
 .../asset-upload/asset-upload-dialog.component.ts  |  77 ++++++++++++++
 22 files changed, 768 insertions(+), 123 deletions(-)

diff --git a/ui/deployment/dev/config.yml b/ui/deployment/dev/config.yml
index 8a72ac568..dc1acdfef 100644
--- a/ui/deployment/dev/config.yml
+++ b/ui/deployment/dev/config.yml
@@ -25,5 +25,6 @@ modules:
   - spDataExplorer
   - spAppOverview
   - spAdd
+  - spAssets
   - spFiles
   - spConfiguration
diff --git a/ui/deployment/modules.yml b/ui/deployment/modules.yml
index f71f14a63..8655b53f0 100644
--- a/ui/deployment/modules.yml
+++ b/ui/deployment/modules.yml
@@ -13,6 +13,21 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+
+spAssets:
+  componentImport: False
+  ng5_moduleName: 'AssetsModule'
+  ng5_component: 'EditorComponent'
+  ng5_componentPath: './editor/editor.component'
+  path: './assets/assets.module'
+  link: 'assets'
+  url: '/editor/:pipeline'
+  title: 'Asset Management'
+  description: 'Manage assets which help assigning pipelines, dashboards and adapters to real-world objects such as machines and plants.'
+  icon: 'precision_manufacturing'
+  homeImage: ''
+  admin: true
+  pageNames: 'PageName.ASSETS'
 spEditor:
   componentImport: True
   ng5_moduleName: 'EditorModule'
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 3f006a246..59e849dcc 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,18 +16,6 @@
  *
  */
 
-export interface StorageItem {
-  _id: string;
-  _rev: string;
-}
-
-export interface AssetLink {
-  linkId: string;
-  linkPaths: string[];
-  linkType: string;
-  linkLabel: string;
-}
-
 export interface AssetType {
   assetIcon: string;
   assetIconColor: string;
@@ -35,11 +23,28 @@ export interface AssetType {
   assetTypeLabel: string;
 }
 
-export interface SimpleAsset extends StorageItem {
+export interface AssetLink {
+  resourceId: string;
+  linkType: 'data-view' | 'dashboard' | 'adapter' | 'stream' | string;
+  linkLabel: string;
+  editingDisabled: boolean;
+}
+
+export interface SpAsset {
   assetId: string;
-  assetType: AssetType;
   assetName: string;
   assetDescription: string;
-  links: AssetLink[];
-  assets: SimpleAsset[];
+
+  assetType: AssetType;
+  assetLinks: AssetLink[];
+
+  assets: SpAsset[];
 }
+
+export interface SpAssetModel extends SpAsset {
+  _id: string;
+  _rev: string;
+
+  removable: boolean;
+}
+
diff --git a/ui/src/app/_enums/page-name.enum.ts b/ui/src/app/_enums/page-name.enum.ts
index 472780aa8..a681bcc02 100644
--- a/ui/src/app/_enums/page-name.enum.ts
+++ b/ui/src/app/_enums/page-name.enum.ts
@@ -30,4 +30,5 @@ export enum PageName {
   FILE_UPLOAD,
   PROFILE,
   SETTINGS,
+  ASSETS
 }
diff --git a/ui/src/app/assets/assets.module.ts b/ui/src/app/assets/assets.module.ts
new file mode 100644
index 000000000..f66dce7fe
--- /dev/null
+++ b/ui/src/app/assets/assets.module.ts
@@ -0,0 +1,94 @@
+/*
+ * 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 { NgModule } from '@angular/core';
+import { MatButtonModule } from '@angular/material/button';
+import { MatCheckboxModule } from '@angular/material/checkbox';
+import { MatGridListModule } from '@angular/material/grid-list';
+import { MatIconModule } from '@angular/material/icon';
+import { MatInputModule } from '@angular/material/input';
+import { MatTooltipModule } from '@angular/material/tooltip';
+import { FlexLayoutModule } from '@angular/flex-layout';
+import { CommonModule } from '@angular/common';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { CustomMaterialModule } from '../CustomMaterial/custom-material.module';
+import { DragDropModule } from '@angular/cdk/drag-drop';
+import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
+import { CoreUiModule } from '../core-ui/core-ui.module';
+import { MatDividerModule } from '@angular/material/divider';
+import { PlatformServicesModule } from '@streampipes/platform-services';
+import { RouterModule } from '@angular/router';
+import { SharedUiModule } from '@streampipes/shared-ui';
+import { SpAssetOverviewComponent } from './components/asset-overview/asset-overview.component';
+import { AssetUploadDialogComponent } from './dialog/asset-upload/asset-upload-dialog.component';
+import { SpAssetDetailsComponent } from './components/asset-details/asset-details.component';
+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';
+
+@NgModule({
+  imports: [
+    CommonModule,
+    CustomMaterialModule,
+    FlexLayoutModule,
+    MatGridListModule,
+    MatButtonModule,
+    MatProgressSpinnerModule,
+    MatIconModule,
+    MatInputModule,
+    MatCheckboxModule,
+    MatDividerModule,
+    MatTooltipModule,
+    FormsModule,
+    DragDropModule,
+    CoreUiModule,
+    ReactiveFormsModule,
+    PlatformServicesModule,
+    RouterModule.forChild([
+      {
+        path: 'assets',
+        children: [
+          {
+            path: '',
+            redirectTo: 'overview',
+            pathMatch: 'full'
+          },
+          {
+            path: 'overview',
+            component: SpAssetOverviewComponent
+          },
+          {
+            path: 'details/:assetId',
+            component: SpAssetDetailsComponent
+          }
+        ]
+      }
+    ]),
+    SharedUiModule,
+    MatTreeModule,
+  ],
+  declarations: [
+    AssetUploadDialogComponent,
+    SpAssetDetailsComponent,
+    SpAssetDetailsPanelComponent,
+    SpAssetOverviewComponent,
+    SpAssetSelectionPanelComponent,
+  ],
+  providers: [],
+})
+export class AssetsModule {}
diff --git a/ui/src/app/_enums/page-name.enum.ts b/ui/src/app/assets/assets.routes.ts
similarity index 75%
copy from ui/src/app/_enums/page-name.enum.ts
copy to ui/src/app/assets/assets.routes.ts
index 472780aa8..bacff6031 100644
--- a/ui/src/app/_enums/page-name.enum.ts
+++ b/ui/src/app/assets/assets.routes.ts
@@ -16,18 +16,11 @@
  *
  */
 
-export enum PageName {
-  HOME,
-  PIPELINE_EDITOR,
-  CONNECT,
-  PIPELINE_OVERVIEW,
-  PIPELINE_DETAILS,
-  DASHBOARD,
-  DATA_EXPLORER,
-  APPS,
-  NOTIFICATIONS,
-  INSTALL_PIPELINE_ELEMENTS,
-  FILE_UPLOAD,
-  PROFILE,
-  SETTINGS,
+import { SpBreadcrumbItem, } from '@streampipes/shared-ui';
+
+export class SpAssetRoutes {
+
+  static BASE: SpBreadcrumbItem = {label: 'Asset Management', link: ['assets']};
+  static CREATE: SpBreadcrumbItem = {label: 'New Asset', link: ['assets', 'create']};
+
 }
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
new file mode 100644
index 000000000..c14309519
--- /dev/null
+++ b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.html
@@ -0,0 +1,39 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxFlex="100" fxLayout="column" class="page-container-padding-inner" *ngIf="asset">
+    <sp-basic-header-title-component [title]="asset.assetName"></sp-basic-header-title-component>
+
+    <sp-basic-inner-panel panelTitle="Basics" outerMargin="20px 0px">
+        <div fxLayout="column" fxFlex="100">
+            <div>Name: {{asset.assetName}}</div>
+            <div>Description: {{asset.assetDescription}}</div>
+        </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>
+            </div>
+        </div>
+    </sp-basic-inner-panel>
+</div>
diff --git a/ui/src/app/_enums/page-name.enum.ts b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.scss
similarity index 77%
copy from ui/src/app/_enums/page-name.enum.ts
copy to ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.scss
index 472780aa8..13cbc4aac 100644
--- a/ui/src/app/_enums/page-name.enum.ts
+++ b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.scss
@@ -15,19 +15,3 @@
  * limitations under the License.
  *
  */
-
-export enum PageName {
-  HOME,
-  PIPELINE_EDITOR,
-  CONNECT,
-  PIPELINE_OVERVIEW,
-  PIPELINE_DETAILS,
-  DASHBOARD,
-  DATA_EXPLORER,
-  APPS,
-  NOTIFICATIONS,
-  INSTALL_PIPELINE_ELEMENTS,
-  FILE_UPLOAD,
-  PROFILE,
-  SETTINGS,
-}
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
new file mode 100644
index 000000000..ae668bc2d
--- /dev/null
+++ b/ui/src/app/assets/components/asset-details/asset-details-panel/asset-details-panel.component.ts
@@ -0,0 +1,18 @@
+import { Component, Input, OnInit } from '@angular/core';
+import { SpAsset } from '@streampipes/platform-services';
+
+
+@Component({
+  selector: 'sp-asset-details-panel-component',
+  templateUrl: './asset-details-panel.component.html',
+  styleUrls: ['./asset-details-panel.component.scss']
+})
+export class SpAssetDetailsPanelComponent implements OnInit {
+
+  @Input()
+  asset: SpAsset;
+
+  ngOnInit(): void {
+  }
+
+}
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
new file mode 100644
index 000000000..ce7849c72
--- /dev/null
+++ b/ui/src/app/assets/components/asset-details/asset-details.component.html
@@ -0,0 +1,51 @@
+<!--
+  ~ 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.
+  ~
+  -->
+<sp-basic-view [showBackLink]="true" [backLinkTarget]="['assets']" [padding]="false">
+
+    <div nav fxFlex="100" fxLayoutAlign="start center" fxLayout="row" class="pl-10">
+
+        <div fxFlex fxLayout="row" fxLayoutAlign="end center">
+
+        </div>
+    </div>
+    <div fxFlex="100" fxLayout="column" *ngIf="asset">
+        <mat-drawer-container class="designer-panel-container h-100 dashboard-grid">
+            <mat-drawer #designerDrawer
+                        [opened]="true"
+                        mode="side"
+                        position="start"
+                        class="designer-panel">
+                <div fxLayout="column" fxFlex="100">
+                    <sp-asset-selection-panel-component
+                            [assetModel]="asset"
+                            (selectedAssetEmitter)="selectedAsset = $event">
+                    </sp-asset-selection-panel-component>
+                </div>
+            </mat-drawer>
+            <mat-drawer-content class="h-100 dashboard-grid">
+                <sp-asset-details-panel-component
+                        *ngIf="selectedAsset"
+                        [asset]="selectedAsset"
+                        fxFlex="100"
+                        fxLayout="row">
+
+                </sp-asset-details-panel-component>
+            </mat-drawer-content>
+        </mat-drawer-container>
+    </div>
+</sp-basic-view>
diff --git a/ui/src/app/_enums/page-name.enum.ts b/ui/src/app/assets/components/asset-details/asset-details.component.scss
similarity index 78%
copy from ui/src/app/_enums/page-name.enum.ts
copy to ui/src/app/assets/components/asset-details/asset-details.component.scss
index 472780aa8..676e7ab69 100644
--- a/ui/src/app/_enums/page-name.enum.ts
+++ b/ui/src/app/assets/components/asset-details/asset-details.component.scss
@@ -16,18 +16,17 @@
  *
  */
 
-export enum PageName {
-  HOME,
-  PIPELINE_EDITOR,
-  CONNECT,
-  PIPELINE_OVERVIEW,
-  PIPELINE_DETAILS,
-  DASHBOARD,
-  DATA_EXPLORER,
-  APPS,
-  NOTIFICATIONS,
-  INSTALL_PIPELINE_ELEMENTS,
-  FILE_UPLOAD,
-  PROFILE,
-  SETTINGS,
+.dashboard-grid {
+  display:flex;
+  flex-direction: column;
+  flex: 1 1 100%;
+}
+
+.designer-panel-container {
+  width: 100%;
+  height: 100%;
+}
+
+.designer-panel {
+  width: 400px;
 }
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
new file mode 100644
index 000000000..7cb5869bd
--- /dev/null
+++ b/ui/src/app/assets/components/asset-details/asset-details.component.ts
@@ -0,0 +1,37 @@
+import { Component, OnInit } from '@angular/core';
+import { SpBreadcrumbService } from '@streampipes/shared-ui';
+import { ActivatedRoute } from '@angular/router';
+import { AssetConstants } from '../../constants/asset.constants';
+import { GenericStorageService, SpAsset, SpAssetModel } from '@streampipes/platform-services';
+import { SpAssetRoutes } from '../../assets.routes';
+
+@Component({
+  selector: 'sp-asset-details-component',
+  templateUrl: './asset-details.component.html',
+  styleUrls: ['./asset-details.component.scss']
+})
+export class SpAssetDetailsComponent implements OnInit {
+
+  asset: SpAssetModel;
+
+  selectedAsset: SpAsset;
+
+  constructor(private breadcrumbService: SpBreadcrumbService,
+              private genericStorageService: GenericStorageService,
+              private route: ActivatedRoute) {
+
+  }
+
+  ngOnInit(): void {
+    const assetId = this.route.snapshot.params.assetId;
+    this.loadAsset(assetId);
+  }
+
+  loadAsset(assetId: string): void {
+    this.genericStorageService.getDocument(AssetConstants.ASSET_APP_DOC_NAME, assetId).subscribe(asset => {
+      this.asset = asset;
+      this.breadcrumbService.updateBreadcrumb([SpAssetRoutes.BASE, {label: this.asset.assetName}]);
+      console.log(this.asset);
+    });
+  }
+}
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
new file mode 100644
index 000000000..66eb05ca6
--- /dev/null
+++ b/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.html
@@ -0,0 +1,51 @@
+<!--
+  ~ 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" class="designer-panel-content" *ngIf="assetModel">
+    <div fxLayout="row" class="sp-tab-bg designer-panel-header">
+        <div fxLayoutAlign="start center" class="designer-panel-title"><h4>Asset Browser</h4></div>
+        <div fxFlex fxLayoutAlign="end end">
+
+        </div>
+    </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-node *matTreeNodeDef="let node" matTreeNodeToggle>
+                    <span (click)="selectNode(node)">{{node.assetName}}</span>
+                </mat-tree-node>
+                <mat-nested-tree-node *matTreeNodeDef="let node; when: hasChild">
+                    <div class="mat-tree-node">
+                        <button mat-icon-button matTreeNodeToggle
+                                [attr.data-cy]="'button-' +node.nodeName"
+                                [attr.aria-label]="'Toggle ' + node.nodeName">
+                            <mat-icon class="mat-icon-rtl-mirror">
+                                {{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
+                            </mat-icon>
+                        </button>
+                        <span (click)="selectNode(node)">{{node.assetName}}</span>
+                    </div>
+                    <div [class.sp-tree-invisible]="!treeControl.isExpanded(node)"
+                         role="group">
+                        <ng-container matTreeNodeOutlet></ng-container>
+                    </div>
+                </mat-nested-tree-node>
+            </mat-tree>
+        </div>
+    </div>
+</div>
diff --git a/ui/projects/streampipes/platform-services/src/lib/model/assets/asset.model.ts b/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.scss
similarity index 62%
copy from ui/projects/streampipes/platform-services/src/lib/model/assets/asset.model.ts
copy to ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.scss
index 3f006a246..0435c97d6 100644
--- a/ui/projects/streampipes/platform-services/src/lib/model/assets/asset.model.ts
+++ b/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.scss
@@ -16,30 +16,38 @@
  *
  */
 
-export interface StorageItem {
-  _id: string;
-  _rev: string;
+.designer-panel-content {
+  padding: 0;
+  overflow-y: auto;
 }
 
-export interface AssetLink {
-  linkId: string;
-  linkPaths: string[];
-  linkType: string;
-  linkLabel: string;
+.designer-panel-config {
+  padding: 0;
 }
 
-export interface AssetType {
-  assetIcon: string;
-  assetIconColor: string;
-  assetTypeCategory: string;
-  assetTypeLabel: string;
+.designer-panel-title {
+  margin-left: 5px;
 }
 
-export interface SimpleAsset extends StorageItem {
-  assetId: string;
-  assetType: AssetType;
-  assetName: string;
-  assetDescription: string;
-  links: AssetLink[];
-  assets: SimpleAsset[];
+.designer-panel-header {
+  border-bottom:1px solid var(--color-tab-border);
+}
+
+.sp-tree-invisible {
+  display: none;
+}
+
+.sp-tree ul,
+.sp-tree li {
+  margin-top: 0;
+  margin-bottom: 0;
+  list-style-type: none;
+}
+
+.sp-tree .mat-nested-tree-node div[role=group] {
+  padding-left: 40px;
+}
+
+.sp-tree div[role=group] > .mat-tree-node {
+  padding-left: 40px;
 }
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
new file mode 100644
index 000000000..ad0c81692
--- /dev/null
+++ b/ui/src/app/assets/components/asset-details/asset-selection-panel/asset-selection-panel.component.ts
@@ -0,0 +1,35 @@
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { SpAsset, SpAssetModel } from '@streampipes/platform-services';
+import { NestedTreeControl } from '@angular/cdk/tree';
+import { MatTreeNestedDataSource } from '@angular/material/tree';
+
+@Component({
+  selector: 'sp-asset-selection-panel-component',
+  templateUrl: './asset-selection-panel.component.html',
+  styleUrls: ['./asset-selection-panel.component.scss']
+})
+export class SpAssetSelectionPanelComponent implements OnInit {
+
+  @Input()
+  assetModel: SpAssetModel;
+
+  @Output()
+  selectedAssetEmitter: EventEmitter<SpAsset> = new EventEmitter<SpAsset>();
+
+  treeControl = new NestedTreeControl<SpAsset>(node => node.assets);
+  dataSource = new MatTreeNestedDataSource<SpAsset>();
+
+  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];
+  }
+
+  selectNode(asset: SpAsset) {
+    this.selectedAssetEmitter.emit(asset);
+  }
+
+
+}
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
new file mode 100644
index 000000000..60c86d681
--- /dev/null
+++ b/ui/src/app/assets/components/asset-overview/asset-overview.component.html
@@ -0,0 +1,113 @@
+<!--
+  ~ 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.
+  ~
+  -->
+<sp-basic-view [showBackLink]="false" [padding]="true">
+
+    <div nav fxFlex="100" fxLayoutAlign="start center" fxLayout="row" class="pl-10">
+        <button mat-button
+                mat-raised-button
+                color="accent"
+                data-cy="connect-create-new-adapter-button"
+                (click)="createNewAsset()">
+            <i class="material-icons">add</i>&nbsp;New asset
+        </button>
+        <div fxFlex fxLayout="row" fxLayoutAlign="end center">
+            <button mat-button mat-icon-button matTooltip="Refresh assets" matTooltipPosition="below" color="accent"
+                    (click)="loadAssets()">
+                <i class="material-icons">
+                    refresh
+                </i>
+            </button>
+            <button mat-button mat-icon-button matTooltip="Refresh assets" matTooltipPosition="below" color="accent"
+                    (click)="uploadAsset()">
+                <i class="material-icons">
+                    cloud_upload
+                </i>
+            </button>
+        </div>
+    </div>
+    <div fxFlex="100" fxLayout="column">
+        <sp-basic-header-title-component title="My assets"></sp-basic-header-title-component>
+        <div fxFlex="100" fxLayout="row" fxLayoutAlign="center start">
+            <sp-basic-inner-panel [showTitle]="false" innerPadding="0" outerMargin="0" fxFlex="90" [hideToolbar]="true">
+                <div fxFlex="100" fxLayout="column" *ngIf="existingAssets.length > 0">
+                    <div fxFlex="100" fxLayout="column">
+                        <table fxFlex="100" mat-table [dataSource]="dataSource" style="width: 100%;" matSort>
+
+                            <ng-container matColumnDef="name">
+                                <th mat-header-cell mat-sort-header *matHeaderCellDef> Name</th>
+                                <td mat-cell *matCellDef="let asset">
+                                    <div fxLayout="row" fxLayoutAlign="start center">
+                                        <div fxLayoutAlign="start center">
+                                            <i class="material-icons">precision_manufacturing</i>
+                                        </div>
+                                        <div fxLayoutAlign="center start" fxLayout="column" class="ml-10">
+                                            <h4 style="margin-bottom:0px;">{{asset.assetName}}</h4>
+                                            <h5>{{asset.assetDescription != '' ? asset.assetDescription : '-'}}</h5>
+                                        </div>
+                                    </div>
+
+                                </td>
+                            </ng-container>
+                            <ng-container matColumnDef="action">
+                                <th mat-header-cell *matHeaderCellDef style="justify-content: center;"> Actions</th>
+                                <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="Manage permissions"-->
+                                            <!--                            matTooltipPosition="above" (click)="showPermissionsDialog(adapter)"><i-->
+                                            <!--                            class="material-icons">share</i>-->
+                                            <!--                    </button>-->
+                </span>
+                                        <span fxFlex fxFlexOrder="3" 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>
+                    </button>
+                </span>
+                                    </div>
+                                </td>
+                            </ng-container>
+
+                            <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
+                            <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
+
+                        </table>
+                    </div>
+                    <div fxFlex="100" fxLayoutAlign="end end">
+                        <mat-paginator [pageSizeOptions]="[5, 10, 25, 100]"
+                                       [pageSize]="20"
+                                       color="accent">
+                        </mat-paginator>
+                    </div>
+                </div>
+                <div fxFlex="100"
+                     fxLayout="column"
+                     fxLayoutAlign="center center"
+                     *ngIf="existingAssets.length == 0">
+                    <h5>(no assets available)</h5>
+                </div>
+            </sp-basic-inner-panel>
+        </div>
+    </div>
+</sp-basic-view>
diff --git a/ui/src/app/_enums/page-name.enum.ts b/ui/src/app/assets/components/asset-overview/asset-overview.component.scss
similarity index 78%
copy from ui/src/app/_enums/page-name.enum.ts
copy to ui/src/app/assets/components/asset-overview/asset-overview.component.scss
index 472780aa8..d1728955a 100644
--- a/ui/src/app/_enums/page-name.enum.ts
+++ b/ui/src/app/assets/components/asset-overview/asset-overview.component.scss
@@ -16,18 +16,6 @@
  *
  */
 
-export enum PageName {
-  HOME,
-  PIPELINE_EDITOR,
-  CONNECT,
-  PIPELINE_OVERVIEW,
-  PIPELINE_DETAILS,
-  DASHBOARD,
-  DATA_EXPLORER,
-  APPS,
-  NOTIFICATIONS,
-  INSTALL_PIPELINE_ELEMENTS,
-  FILE_UPLOAD,
-  PROFILE,
-  SETTINGS,
+.ml-10 {
+  margin-left: 10px;
 }
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
new file mode 100644
index 000000000..225a0a9cd
--- /dev/null
+++ b/ui/src/app/assets/components/asset-overview/asset-overview.component.ts
@@ -0,0 +1,93 @@
+/*
+ * 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 { MatTableDataSource } from '@angular/material/table';
+import { GenericStorageService, SpAssetModel } from '@streampipes/platform-services';
+import { AssetConstants } from '../../constants/asset.constants';
+import { DialogService, PanelType, SpBreadcrumbService } from '@streampipes/shared-ui';
+import { SpAssetRoutes } from '../../assets.routes';
+import { AssetUploadDialogComponent } from '../../dialog/asset-upload/asset-upload-dialog.component';
+import { Router } from '@angular/router';
+
+@Component({
+  selector: 'sp-asset-overview-component',
+  templateUrl: './asset-overview.component.html',
+  styleUrls: ['./asset-overview.component.scss']
+})
+export class SpAssetOverviewComponent implements OnInit {
+
+  existingAssets: SpAssetModel[] = [];
+
+  displayedColumns: string[] = ['name', 'action'];
+
+  dataSource: MatTableDataSource<SpAssetModel>;
+
+  constructor(private genericStorageService: GenericStorageService,
+              private breadcrumbService: SpBreadcrumbService,
+              private dialogService: DialogService,
+              private router: Router) {
+
+  }
+
+  ngOnInit(): void {
+    this.breadcrumbService.updateBreadcrumb(this.breadcrumbService.getRootLink(SpAssetRoutes.BASE));
+    this.loadAssets();
+  }
+
+  loadAssets(): void {
+    this.genericStorageService.getAllDocuments(AssetConstants.ASSET_APP_DOC_NAME).subscribe(result => {
+      this.existingAssets = result as SpAssetModel[];
+      this.dataSource = new MatTableDataSource<SpAssetModel>(this.existingAssets);
+    });
+  }
+
+  createNewAsset() {
+
+  }
+
+  uploadAsset() {
+    const dialogRef = this.dialogService.open(AssetUploadDialogComponent, {
+      panelType: PanelType.SLIDE_IN_PANEL,
+      title: 'Upload asset model',
+      width: '40vw',
+    });
+
+    dialogRef.afterClosed().subscribe(reload => {
+      if (reload) {
+        this.loadAssets();
+      }
+    });
+  }
+
+  goToDetailsView(asset: SpAssetModel) {
+    this.router.navigate(['assets', 'details', asset._id]);
+  }
+
+  deleteAsset(asset: SpAssetModel) {
+    this.genericStorageService.deleteDocument(
+      AssetConstants.ASSET_APP_DOC_NAME,
+      asset._id,
+      asset._rev)
+      .subscribe(result => {
+        this.loadAssets();
+      });
+  }
+
+
+}
diff --git a/ui/src/app/_enums/page-name.enum.ts b/ui/src/app/assets/constants/asset.constants.ts
similarity index 78%
copy from ui/src/app/_enums/page-name.enum.ts
copy to ui/src/app/assets/constants/asset.constants.ts
index 472780aa8..c0bcb1988 100644
--- a/ui/src/app/_enums/page-name.enum.ts
+++ b/ui/src/app/assets/constants/asset.constants.ts
@@ -16,18 +16,7 @@
  *
  */
 
-export enum PageName {
-  HOME,
-  PIPELINE_EDITOR,
-  CONNECT,
-  PIPELINE_OVERVIEW,
-  PIPELINE_DETAILS,
-  DASHBOARD,
-  DATA_EXPLORER,
-  APPS,
-  NOTIFICATIONS,
-  INSTALL_PIPELINE_ELEMENTS,
-  FILE_UPLOAD,
-  PROFILE,
-  SETTINGS,
+export class AssetConstants {
+
+  public static ASSET_APP_DOC_NAME = 'asset-management';
 }
diff --git a/ui/src/app/assets/dialog/asset-upload/asset-upload-dialog.component.html b/ui/src/app/assets/dialog/asset-upload/asset-upload-dialog.component.html
new file mode 100644
index 000000000..9cd6bf1ce
--- /dev/null
+++ b/ui/src/app/assets/dialog/asset-upload/asset-upload-dialog.component.html
@@ -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.
+~
+-->
+
+
+<div class="sp-dialog-container">
+    <div class="sp-dialog-content p-15">
+        <div fxFlex="100" fxLayout="column">
+            <div fxFlex style="margin:5px;width:100%" fxLayout="column">
+                <mat-form-field style="width: 95%" (click)="fileInput.click();" color="accent">
+                    <mat-label>Upload JSON file</mat-label>
+                    <input matInput placeholder="File" disabled (value)="fileName">
+                    <input #fileInput type="file" style="display:none;"
+                           (change)="handleFileInput($event.target.files)"
+                           data-cy="sp-file-management-file-input">
+                    <div>
+                        {{fileName}}
+                        <mat-progress-bar mode="determinate" value="{{uploadStatus}}" *ngIf="uploadStatus > 0" color="accent"></mat-progress-bar>
+                    </div>
+                    <button color="accent" matSuffix
+                            mat-button style="min-width: 0px">
+                        <mat-icon *ngIf="uploadStatus < 99">insert_drive_file</mat-icon>
+                        <mat-icon *ngIf="uploadStatus == 100" class="green-icon">check_circle</mat-icon>
+                    </button>
+                    <mat-error *ngIf="!hasInput">
+                        {{errorMessage}}
+                    </mat-error>
+                </mat-form-field>
+            </div>
+            <div fxFlex="100">
+                <mat-form-field style="width: 100%;height: 100%;" color="accent">
+                    <mat-label>Insert model</mat-label>
+                    <textarea matInput [(ngModel)]="jsonModel" style="height: 100%;"
+                              cdkTextareaAutosize
+                              cdkAutosizeMinRows="30"
+                              cdkAutosizeMaxRows="30"></textarea>
+                </mat-form-field>
+            </div>
+        </div>
+    </div>
+    <mat-divider></mat-divider>
+    <div class="sp-dialog-actions">
+        <button mat-button
+                mat-raised-button
+                color="accent"
+                [disabled]="jsonModel === undefined"
+                (click)="store()" data-cy="sp-file-management-store-file" style="margin-right:10px;">
+            Create asset
+        </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/_enums/page-name.enum.ts b/ui/src/app/assets/dialog/asset-upload/asset-upload-dialog.component.scss
similarity index 78%
copy from ui/src/app/_enums/page-name.enum.ts
copy to ui/src/app/assets/dialog/asset-upload/asset-upload-dialog.component.scss
index 472780aa8..d25ee7413 100644
--- a/ui/src/app/_enums/page-name.enum.ts
+++ b/ui/src/app/assets/dialog/asset-upload/asset-upload-dialog.component.scss
@@ -16,18 +16,4 @@
  *
  */
 
-export enum PageName {
-  HOME,
-  PIPELINE_EDITOR,
-  CONNECT,
-  PIPELINE_OVERVIEW,
-  PIPELINE_DETAILS,
-  DASHBOARD,
-  DATA_EXPLORER,
-  APPS,
-  NOTIFICATIONS,
-  INSTALL_PIPELINE_ELEMENTS,
-  FILE_UPLOAD,
-  PROFILE,
-  SETTINGS,
-}
+@import 'src/scss/sp/sp-dialog';
\ No newline at end of file
diff --git a/ui/src/app/assets/dialog/asset-upload/asset-upload-dialog.component.ts b/ui/src/app/assets/dialog/asset-upload/asset-upload-dialog.component.ts
new file mode 100644
index 000000000..b1f52f129
--- /dev/null
+++ b/ui/src/app/assets/dialog/asset-upload/asset-upload-dialog.component.ts
@@ -0,0 +1,77 @@
+/*
+ * 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 { DialogRef } from '@streampipes/shared-ui';
+import { GenericStorageService } from '@streampipes/platform-services';
+import { AssetConstants } from '../../constants/asset.constants';
+
+@Component({
+  selector: 'sp-file-upload-dialog-component',
+  templateUrl: './asset-upload-dialog.component.html',
+  styleUrls: ['./asset-upload-dialog.component.scss']
+})
+export class AssetUploadDialogComponent implements OnInit {
+
+  inputValue: string;
+  fileName: string;
+
+  jsonModel: string;
+
+  hasInput: boolean;
+  errorMessage = 'Please enter a value';
+
+  uploadStatus = 0;
+
+  constructor(private dialogRef: DialogRef<AssetUploadDialogComponent>,
+              private genericStorageService: GenericStorageService) {
+
+  }
+
+  ngOnInit(): void {
+  }
+
+  handleFileInput(files: any) {
+    this.uploadStatus = 0;
+
+    const fr = new FileReader();
+
+    fr.onload = (ev => {
+      const jsonObject = JSON.parse(ev.target.result as string);
+      this.jsonModel = JSON.stringify(jsonObject, null, 2);
+    });
+
+    fr.readAsText(files.item(0));
+  }
+
+  store() {
+    this.uploadStatus = 0;
+    if (this.jsonModel !== undefined) {
+      const jsonObject = JSON.parse(this.jsonModel);
+      jsonObject._rev = undefined;
+      this.genericStorageService.createDocument(AssetConstants.ASSET_APP_DOC_NAME, jsonObject).subscribe(result => {
+        this.dialogRef.close(true);
+      });
+    }
+  }
+
+  cancel() {
+    this.dialogRef.close();
+  }
+
+}