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

riemer pushed a commit to branch 
3033-support-modification-of-individual-data-views
in repository https://gitbox.apache.org/repos/asf/streampipes.git


The following commit(s) were added to 
refs/heads/3033-support-modification-of-individual-data-views by this push:
     new 20c53f8e7a feat(#3033): Support modification of data views
20c53f8e7a is described below

commit 20c53f8e7aee000792b7c32f280faf874db3b209
Author: Dominik Riemer <[email protected]>
AuthorDate: Mon Jul 15 21:14:40 2024 +0200

    feat(#3033): Support modification of data views
---
 .../model/datalake/DataExplorerWidgetModel.java    |   8 +
 .../lib/apis/data-view-data-explorer.service.ts    |  26 +---
 .../src/lib/model/gen/streampipes-model.ts         |  25 +--
 .../data-explorer-data-view.component.html         |  74 +++++++++
 .../data-explorer-data-view.component.scss         |  36 +++++
 .../data-view/data-explorer-data-view.component.ts | 120 +++++++++++++++
 .../data-explorer-data-view-toolbar.component.html |  54 +++++++
 .../data-explorer-data-view-toolbar.component.scss |   0
 .../data-explorer-data-view-toolbar.component.ts}  |  32 ++--
 ...data-explorer-dashboard-overview.component.html | 144 -----------------
 .../data-explorer-dashboard-overview.component.ts  | 171 ---------------------
 ...data-explorer-dashboard-overview.component.html | 114 ++++++++++++++
 .../data-explorer-dashboard-overview.component.ts  | 126 +++++++++++++++
 ...data-explorer-data-view-overview.component.html |  95 ++++++++++++
 .../data-explorer-data-view-overview.component.ts  |  77 ++++++++++
 .../overview/data-explorer-overview.component.html |  56 +++++++
 ....scss => data-explorer-overview.component.scss} |   0
 .../overview/data-explorer-overview.component.ts   |  85 ++++++++++
 .../overview/data-explorer-overview.directive.ts   |  65 ++++++++
 ui/src/app/data-explorer/data-explorer.module.ts   |  26 +++-
 .../services/data-explorer-dashboard.service.ts    |  42 +++++
 21 files changed, 1002 insertions(+), 374 deletions(-)

diff --git 
a/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/DataExplorerWidgetModel.java
 
b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/DataExplorerWidgetModel.java
index 2371363acc..e9ac5bc159 100644
--- 
a/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/DataExplorerWidgetModel.java
+++ 
b/streampipes-model/src/main/java/org/apache/streampipes/model/datalake/DataExplorerWidgetModel.java
@@ -40,6 +40,9 @@ public class DataExplorerWidgetModel extends DashboardEntity {
   @JsonSerialize(using = CustomMapSerializer.class, as = Map.class)
   private Map<String, Object> dataConfig;
 
+  @JsonSerialize(using = CustomMapSerializer.class, as = Map.class)
+  private Map<String, Object> timeSettings;
+
   private String pipelineId;
   private String measureName;
 
@@ -49,6 +52,7 @@ public class DataExplorerWidgetModel extends DashboardEntity {
     this.baseAppearanceConfig = new HashMap<>();
     this.visualizationConfig = new HashMap<>();
     this.dataConfig = new HashMap<>();
+    this.timeSettings = new HashMap<>();
   }
 
   public String getWidgetId() {
@@ -107,4 +111,8 @@ public class DataExplorerWidgetModel extends 
DashboardEntity {
     this.measureName = measureName;
   }
 
+  public Map<String, Object> getTimeSettings() {
+    return this.timeSettings;
+  }
+
 }
diff --git 
a/ui/projects/streampipes/platform-services/src/lib/apis/data-view-data-explorer.service.ts
 
b/ui/projects/streampipes/platform-services/src/lib/apis/data-view-data-explorer.service.ts
index a9315adca6..68c1988cb4 100644
--- 
a/ui/projects/streampipes/platform-services/src/lib/apis/data-view-data-explorer.service.ts
+++ 
b/ui/projects/streampipes/platform-services/src/lib/apis/data-view-data-explorer.service.ts
@@ -21,7 +21,6 @@ import { Observable } from 'rxjs';
 import { map } from 'rxjs/operators';
 import { Dashboard } from '../model/dashboard/dashboard.model';
 import { Injectable } from '@angular/core';
-import { DatalakeRestService } from './datalake-rest.service';
 import {
     DataExplorerWidgetModel,
     DataLakeMeasure,
@@ -34,32 +33,13 @@ import { SharedDatalakeRestService } from 
'./shared-dashboard.service';
 export class DataViewDataExplorerService {
     constructor(
         private http: HttpClient,
-        private dataLakeRestService: DatalakeRestService,
         private sharedDatalakeRestService: SharedDatalakeRestService,
     ) {}
 
-    getVisualizableData(): Observable<DataLakeMeasure[]> {
-        return this.dataLakeRestService.getAllMeasurementSeries().pipe(
-            map(data => {
-                return (data as any[]).map(d =>
-                    DataLakeMeasure.fromData(d as DataLakeMeasure),
-                );
-            }),
-        );
-    }
-
     getDataViews(): Observable<Dashboard[]> {
         return this.sharedDatalakeRestService.getDashboards(this.dashboardUrl);
     }
 
-    getDataView(dataViewId: string): Observable<Dashboard> {
-        return this.http.get(this.dashboardUrl + '/' + dataViewId).pipe(
-            map(data => {
-                return data as Dashboard;
-            }),
-        );
-    }
-
     updateDashboard(dashboard: Dashboard): Observable<Dashboard> {
         return this.sharedDatalakeRestService.updateDashboard(
             this.dashboardUrl,
@@ -97,6 +77,12 @@ export class DataViewDataExplorerService {
         return `${this.baseUrl}/api/v3/datalake/dashboard/widgets`;
     }
 
+    getAllWidgets(): Observable<DataExplorerWidgetModel[]> {
+        return this.http
+            .get(this.dashboardWidgetUrl)
+            .pipe(map(res => res as DataExplorerWidgetModel[]));
+    }
+
     getWidget(widgetId: string): Observable<DataExplorerWidgetModel> {
         return this.http.get(this.dashboardWidgetUrl + '/' + widgetId).pipe(
             map(response => {
diff --git 
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
 
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
index cf79d51045..646a667f10 100644
--- 
a/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
+++ 
b/ui/projects/streampipes/platform-services/src/lib/model/gen/streampipes-model.ts
@@ -1,26 +1,7 @@
-/*
- * 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.
- */
-
 /* tslint:disable */
 /* eslint-disable */
 // @ts-nocheck
-// Generated using typescript-generator version 3.2.1263 on 2024-06-30 
09:10:19.
+// Generated using typescript-generator version 3.2.1263 on 2024-07-13 
11:00:10.
 
 export class NamedStreamPipesEntity implements Storable {
     '@class':
@@ -1097,6 +1078,7 @@ export class DataExplorerWidgetModel extends 
DashboardEntity {
     dataConfig: { [index: string]: any };
     measureName: string;
     pipelineId: string;
+    timeSettings: { [index: string]: any };
     visualizationConfig: { [index: string]: any };
     widgetId: string;
     widgetType: string;
@@ -1118,6 +1100,9 @@ export class DataExplorerWidgetModel extends 
DashboardEntity {
         );
         instance.measureName = data.measureName;
         instance.pipelineId = data.pipelineId;
+        instance.timeSettings = __getCopyObjectFn(__identity<any>())(
+            data.timeSettings,
+        );
         instance.visualizationConfig = __getCopyObjectFn(__identity<any>())(
             data.visualizationConfig,
         );
diff --git 
a/ui/src/app/data-explorer/components/data-view/data-explorer-data-view.component.html
 
b/ui/src/app/data-explorer/components/data-view/data-explorer-data-view.component.html
new file mode 100644
index 0000000000..4cd25092a3
--- /dev/null
+++ 
b/ui/src/app/data-explorer/components/data-view/data-explorer-data-view.component.html
@@ -0,0 +1,74 @@
+<!--
+  ~ 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
+    [backLinkTarget]="['dataexplorer']"
+    [showBackLink]="true"
+    *ngIf="dataViewLoaded"
+>
+    <div
+        nav
+        fxFlex="100"
+        fxLayoutAlign="start center"
+        fxLayout="row"
+        class="pl-10"
+    >
+        <sp-data-explorer-data-view-toolbar
+            [timeSettings]="timeSettings"
+            (updateDateRangeEmitter)="updateDateRange($event)"
+            (saveDataViewEmitter)="saveDataView()"
+            fxFlex="100"
+        >
+        </sp-data-explorer-data-view-toolbar>
+    </div>
+    <div fxFlex="100" fxLayout="column">
+        <mat-drawer-container
+            class="designer-panel-container h-100 dashboard-grid"
+        >
+            <mat-drawer
+                [opened]="editMode"
+                mode="side"
+                position="end"
+                class="designer-panel"
+            >
+                <div fxLayout="column" fxFlex="100">
+                    <sp-data-explorer-designer-panel
+                        [currentlyConfiguredWidget]="dataView"
+                        [dataLakeMeasure]="dataLakeMeasure"
+                        fxFlex="100"
+                    >
+                    </sp-data-explorer-designer-panel>
+                </div>
+            </mat-drawer>
+            <mat-drawer-content class="h-100 dashboard-grid">
+                <div #panel fxFlex="100" fxLayout="column">
+                    <sp-data-explorer-dashboard-widget
+                        *ngIf="dataView && gridsterItemComponent"
+                        [configuredWidget]="dataView"
+                        [gridsterItemComponent]="gridsterItemComponent"
+                        [timeSettings]="timeSettings"
+                        [dataLakeMeasure]="
+                            dataView.dataConfig.sourceConfigs[0].measure
+                        "
+                    >
+                    </sp-data-explorer-dashboard-widget>
+                </div>
+            </mat-drawer-content>
+        </mat-drawer-container>
+    </div>
+</sp-basic-view>
diff --git 
a/ui/src/app/data-explorer/components/data-view/data-explorer-data-view.component.scss
 
b/ui/src/app/data-explorer/components/data-view/data-explorer-data-view.component.scss
new file mode 100644
index 0000000000..23729248d6
--- /dev/null
+++ 
b/ui/src/app/data-explorer/components/data-view/data-explorer-data-view.component.scss
@@ -0,0 +1,36 @@
+.fixed-height {
+    height: 50px;
+}
+
+.data-explorer-options {
+    padding: 0px;
+}
+
+.data-explorer-options-item {
+    display: inline;
+    margin-right: 10px;
+}
+
+.m-20 {
+    margin: 20px;
+}
+
+.h-100 {
+    height: 100%;
+}
+
+.dashboard-grid {
+    display: flex;
+    flex-direction: column;
+    flex: 1 1 100%;
+}
+
+.designer-panel-container {
+    width: 100%;
+    height: 100%;
+}
+
+.designer-panel {
+    width: 450px;
+    border: 1px solid var(--color-tab-border);
+}
diff --git 
a/ui/src/app/data-explorer/components/data-view/data-explorer-data-view.component.ts
 
b/ui/src/app/data-explorer/components/data-view/data-explorer-data-view.component.ts
new file mode 100644
index 0000000000..4eb202c0ad
--- /dev/null
+++ 
b/ui/src/app/data-explorer/components/data-view/data-explorer-data-view.component.ts
@@ -0,0 +1,120 @@
+/*
+ * 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, ElementRef, OnInit, ViewChild } from '@angular/core';
+import {
+    DataExplorerWidgetModel,
+    DataLakeMeasure,
+    DataViewDataExplorerService,
+    TimeSettings,
+} from '@streampipes/platform-services';
+import { ActivatedRoute, Router } from '@angular/router';
+import { TimeSelectionService } from '../../services/time-selection.service';
+
+@Component({
+    selector: 'sp-data-explorer-data-view',
+    templateUrl: './data-explorer-data-view.component.html',
+    styleUrls: ['./data-explorer-data-view.component.scss'],
+})
+export class DataExplorerDataViewComponent implements OnInit {
+    dataViewLoaded = false;
+    timeSettings: TimeSettings;
+
+    editMode = true;
+    dataView: DataExplorerWidgetModel;
+    dataLakeMeasure: DataLakeMeasure;
+    gridsterItemComponent: any;
+
+    @ViewChild('panel', { static: false }) outerPanel: ElementRef;
+
+    constructor(
+        private route: ActivatedRoute,
+        private router: Router,
+        private dataViewService: DataViewDataExplorerService,
+        private timeSelectionService: TimeSelectionService,
+    ) {}
+
+    ngOnInit() {
+        const dataViewId = this.route.snapshot.params.id;
+        this.editMode = this.route.snapshot.queryParams.editMode;
+
+        if (dataViewId) {
+            this.dataViewService.getWidget(dataViewId).subscribe(res => {
+                this.dataView = res;
+                if (!this.dataView.timeSettings?.startTime) {
+                    this.timeSettings = this.makeDefaultTimeSettings();
+                } else {
+                    this.timeSettings = this.dataView
+                        .timeSettings as TimeSettings;
+                }
+                this.afterDataViewLoaded();
+            });
+        } else {
+            this.createWidget();
+            this.afterDataViewLoaded();
+        }
+    }
+
+    afterDataViewLoaded(): void {
+        this.dataViewLoaded = true;
+        setTimeout(() => {
+            const width = this.outerPanel.nativeElement.offsetWidth;
+            const height = this.outerPanel.nativeElement.offsetHeight;
+            this.gridsterItemComponent = { width, height };
+            this.timeSelectionService.notify(this.timeSettings);
+        });
+    }
+
+    makeDefaultTimeSettings(): TimeSettings {
+        return {
+            dynamicSelection: 1440,
+            endTime: new Date().getTime(),
+            startTime: new Date().getTime() - 1000 * 24 * 60 * 60,
+        };
+    }
+
+    createWidget() {
+        this.dataLakeMeasure = new DataLakeMeasure();
+        this.dataView = new DataExplorerWidgetModel();
+        this.dataView['@class'] =
+            'org.apache.streampipes.model.datalake.DataExplorerWidgetModel';
+        this.dataView.baseAppearanceConfig = {};
+        this.dataView.baseAppearanceConfig.widgetTitle = 'New Widget';
+        this.dataView.dataConfig = {};
+        this.dataView.dataConfig.ignoreMissingValues = false;
+        this.dataView.baseAppearanceConfig.backgroundColor = '#FFFFFF';
+        this.dataView.baseAppearanceConfig.textColor = '#3e3e3e';
+        this.dataView.timeSettings = this.makeDefaultTimeSettings();
+        this.dataView = { ...this.dataView };
+    }
+
+    saveDataView(): void {
+        this.dataView.timeSettings = this.timeSettings;
+        const observable = this.editMode
+            ? this.dataViewService.updateWidget(this.dataView)
+            : this.dataViewService.saveWidget(this.dataView);
+        observable.subscribe(() => {
+            this.router.navigate(['dataexplorer']);
+        });
+    }
+
+    updateDateRange(timeSettings: TimeSettings) {
+        this.timeSettings = timeSettings;
+        this.timeSelectionService.notify(timeSettings);
+    }
+}
diff --git 
a/ui/src/app/data-explorer/components/data-view/data-view-toolbar/data-explorer-data-view-toolbar.component.html
 
b/ui/src/app/data-explorer/components/data-view/data-view-toolbar/data-explorer-data-view-toolbar.component.html
new file mode 100644
index 0000000000..4be9360243
--- /dev/null
+++ 
b/ui/src/app/data-explorer/components/data-view/data-view-toolbar/data-explorer-data-view-toolbar.component.html
@@ -0,0 +1,54 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+<div fxLayout="row" fxFlex="100">
+    <div
+        class="data-explorer-options-item"
+        fxLayoutAlign="start center"
+        fxLayout="row"
+        fxFlex="100"
+        *ngIf="editMode"
+    >
+        <button
+            mat-raised-button
+            color="accent"
+            matTooltip="Save"
+            class="edit-menu-btn"
+            (click)="saveDataViewEmitter.emit()"
+            data-cy="save-data-explorer-widget-btn"
+        >
+            <mat-icon>save</mat-icon>
+            Save data view
+        </button>
+        <span fxFlex></span>
+        <div
+            class="data-explorer-options-item"
+            style="margin-right: 0"
+            fxLayoutAlign="end center"
+            fxFlex
+            fxLayout="row"
+        >
+            <sp-time-range-selector
+                *ngIf="editMode || timeRangeVisible"
+                (dateRangeEmitter)="updateDateRangeEmitter.emit($event)"
+                [dateRange]="timeSettings"
+            >
+            </sp-time-range-selector>
+        </div>
+    </div>
+</div>
diff --git 
a/ui/src/app/data-explorer/components/data-view/data-view-toolbar/data-explorer-data-view-toolbar.component.scss
 
b/ui/src/app/data-explorer/components/data-view/data-view-toolbar/data-explorer-data-view-toolbar.component.scss
new file mode 100644
index 0000000000..e69de29bb2
diff --git 
a/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.scss
 
b/ui/src/app/data-explorer/components/data-view/data-view-toolbar/data-explorer-data-view-toolbar.component.ts
similarity index 54%
copy from 
ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.scss
copy to 
ui/src/app/data-explorer/components/data-view/data-view-toolbar/data-explorer-data-view-toolbar.component.ts
index 9103beb12d..d96a1b93b6 100644
--- 
a/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.scss
+++ 
b/ui/src/app/data-explorer/components/data-view/data-view-toolbar/data-explorer-data-view-toolbar.component.ts
@@ -16,22 +16,26 @@
  *
  */
 
-.mat-mdc-header-cell {
-    font-weight: bold;
-}
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { TimeSettings } from '@streampipes/platform-services';
 
-.w-100 {
-    width: 100%;
-}
+@Component({
+    selector: 'sp-data-explorer-data-view-toolbar',
+    templateUrl: './data-explorer-data-view-toolbar.component.html',
+    styleUrls: ['./data-explorer-data-view-toolbar.component.scss'],
+})
+export class DataExplorerDataViewToolbarComponent {
+    @Input()
+    editMode = true;
 
-.p-2 {
-    padding: 2px;
-}
+    @Input()
+    timeSettings: TimeSettings;
 
-.m-20 {
-    margin: 20px;
-}
+    timeRangeVisible = true;
+
+    @Output()
+    saveDataViewEmitter: EventEmitter<void> = new EventEmitter();
 
-.mr-10 {
-    margin-right: 10px;
+    @Output()
+    updateDateRangeEmitter: EventEmitter<TimeSettings> = new EventEmitter();
 }
diff --git 
a/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.html
 
b/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.html
deleted file mode 100644
index 0aadcd6c57..0000000000
--- 
a/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.html
+++ /dev/null
@@ -1,144 +0,0 @@
-<!--
-  ~ 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="open-new-data-view-dialog"
-            (click)="openNewDataViewDialog()"
-            class="mr-10"
-            *ngIf="hasDataExplorerWritePrivileges"
-        >
-            <i class="material-icons">add</i>
-            <span>New Data View</span>
-        </button>
-    </div>
-    <div fxFlex="100" fxLayout="column">
-        <sp-basic-header-title-component
-            title="Data Views"
-        ></sp-basic-header-title-component>
-        <div fxFlex="100" fxLayout="row" fxLayoutAlign="center start">
-            <sp-table
-                fxFlex="90"
-                [columns]="displayedColumns"
-                [dataSource]="dataSource"
-            >
-                <ng-container matColumnDef="name">
-                    <th
-                        fxFlex="60"
-                        fxLayoutAlign="start center"
-                        mat-header-cell
-                        *matHeaderCellDef
-                    >
-                        Data View
-                    </th>
-                    <td
-                        fxFlex="60"
-                        fxLayoutAlign="start center"
-                        mat-cell
-                        *matCellDef="let element"
-                    >
-                        {{ element.name }}<br />
-                        {{ element.description }}
-                    </td>
-                </ng-container>
-
-                <ng-container matColumnDef="actions">
-                    <th
-                        fxFlex="40"
-                        fxLayoutAlign="center center"
-                        mat-header-cell
-                        *matHeaderCellDef
-                    ></th>
-                    <td
-                        fxFlex="40"
-                        fxLayoutAlign="start center"
-                        mat-cell
-                        *matCellDef="let element"
-                    >
-                        <div
-                            fxLayout="row"
-                            fxFlex="100"
-                            fxLayoutAlign="end center"
-                        >
-                            <button
-                                mat-icon-button
-                                color="accent"
-                                matTooltip="Show data view"
-                                (click)="showDashboard(element)"
-                            >
-                                <i class="material-icons">visibility</i>
-                            </button>
-                            <button
-                                mat-icon-button
-                                color="accent"
-                                matTooltip="Edit data view"
-                                *ngIf="hasDataExplorerWritePrivileges"
-                                [attr.data-cy]="
-                                    'edit-dashboard-' + element.name
-                                "
-                                (click)="editDashboard(element)"
-                            >
-                                <i class="material-icons">edit</i>
-                            </button>
-                            <button
-                                mat-icon-button
-                                color="accent"
-                                matTooltip="Edit data view settings"
-                                *ngIf="hasDataExplorerWritePrivileges"
-                                (click)="openEditDataViewDialog(element)"
-                            >
-                                <i class="material-icons">settings</i>
-                            </button>
-                            <button
-                                mat-icon-button
-                                color="accent"
-                                matTooltip="Manage permissions"
-                                *ngIf="isAdmin"
-                                (click)="showPermissionsDialog(element)"
-                            >
-                                <i class="material-icons">share</i>
-                            </button>
-                            <button
-                                mat-icon-button
-                                color="accent"
-                                matTooltip="Delete data view"
-                                *ngIf="hasDataExplorerDeletePrivileges"
-                                [attr.data-cy]="
-                                    'delete-dashboard-' + element.name
-                                "
-                                (click)="openDeleteDashboardDialog(element)"
-                            >
-                                <i class="material-icons">delete</i>
-                            </button>
-                        </div>
-                    </td>
-                </ng-container>
-            </sp-table>
-        </div>
-    </div>
-</sp-basic-view>
diff --git 
a/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.ts
 
b/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.ts
deleted file mode 100644
index 6a5e38a4b5..0000000000
--- 
a/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.ts
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 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, OnDestroy, OnInit } from '@angular/core';
-import { MatTableDataSource } from '@angular/material/table';
-import { DataExplorerEditDataViewDialogComponent } from 
'../../dialogs/edit-dashboard/data-explorer-edit-data-view-dialog.component';
-import {
-    Dashboard,
-    DataViewDataExplorerService,
-} from '@streampipes/platform-services';
-import {
-    CurrentUserService,
-    DialogService,
-    PanelType,
-    SpBreadcrumbService,
-} from '@streampipes/shared-ui';
-import { ObjectPermissionDialogComponent } from 
'../../../core-ui/object-permission-dialog/object-permission-dialog.component';
-import { UserRole } from '../../../_enums/user-role.enum';
-import { AuthService } from '../../../services/auth.service';
-import { UserPrivilege } from '../../../_enums/user-privilege.enum';
-import { Router } from '@angular/router';
-import { SpDataExplorerRoutes } from '../../data-explorer.routes';
-import { Subscription } from 'rxjs';
-
-@Component({
-    selector: 'sp-data-explorer-dashboard-overview',
-    templateUrl: './data-explorer-dashboard-overview.component.html',
-    styleUrls: ['./data-explorer-dashboard-overview.component.scss'],
-})
-export class DataExplorerDashboardOverviewComponent
-    implements OnInit, OnDestroy
-{
-    dataSource = new MatTableDataSource<Dashboard>();
-    displayedColumns: string[] = [];
-    dashboards: Dashboard[] = [];
-
-    isAdmin = false;
-
-    hasDataExplorerWritePrivileges = false;
-    hasDataExplorerDeletePrivileges = false;
-
-    authSubscription: Subscription;
-
-    constructor(
-        private dataViewService: DataViewDataExplorerService,
-        private dashboardService: DataViewDataExplorerService,
-        public dialogService: DialogService,
-        private authService: AuthService,
-        private currentUserService: CurrentUserService,
-        private router: Router,
-        private breadcrumbService: SpBreadcrumbService,
-    ) {}
-
-    ngOnInit(): void {
-        this.breadcrumbService.updateBreadcrumb(
-            this.breadcrumbService.getRootLink(SpDataExplorerRoutes.BASE),
-        );
-        this.authSubscription = this.currentUserService.user$.subscribe(
-            user => {
-                this.hasDataExplorerWritePrivileges = this.authService.hasRole(
-                    UserPrivilege.PRIVILEGE_WRITE_DATA_EXPLORER_VIEW,
-                );
-                this.hasDataExplorerDeletePrivileges = 
this.authService.hasRole(
-                    UserPrivilege.PRIVILEGE_DELETE_DATA_EXPLORER_VIEW,
-                );
-                this.isAdmin = user.roles.indexOf(UserRole.ROLE_ADMIN) > -1;
-                this.displayedColumns = ['name', 'actions'];
-            },
-        );
-
-        this.getDashboards();
-    }
-
-    ngOnDestroy() {
-        if (this.authSubscription) {
-            this.authSubscription.unsubscribe();
-        }
-    }
-
-    getDashboards() {
-        this.dataViewService.getDataViews().subscribe(data => {
-            this.dashboards = data.sort((a, b) => 
a.name.localeCompare(b.name));
-            this.dataSource.data = this.dashboards;
-        });
-    }
-
-    openNewDataViewDialog() {
-        const dataViewDashboard: Dashboard = {};
-        dataViewDashboard.dashboardGeneralSettings = {};
-        dataViewDashboard.widgets = [];
-        dataViewDashboard.name = '';
-
-        this.openDataViewModificationDialog(true, dataViewDashboard);
-    }
-
-    openDataViewModificationDialog(createMode: boolean, dashboard: Dashboard) {
-        const dialogRef = this.dialogService.open(
-            DataExplorerEditDataViewDialogComponent,
-            {
-                panelType: PanelType.STANDARD_PANEL,
-                title: createMode ? 'New Data View' : 'Edit Data View',
-                width: '70vw',
-                data: {
-                    createMode: createMode,
-                    dashboard: dashboard,
-                },
-            },
-        );
-
-        dialogRef.afterClosed().subscribe(result => {
-            this.getDashboards();
-        });
-    }
-
-    showPermissionsDialog(dashboard: Dashboard) {
-        const dialogRef = this.dialogService.open(
-            ObjectPermissionDialogComponent,
-            {
-                panelType: PanelType.SLIDE_IN_PANEL,
-                title: 'Manage permissions',
-                width: '50vw',
-                data: {
-                    objectInstanceId: dashboard.elementId,
-                    headerTitle:
-                        'Manage permissions for dashboard ' + dashboard.name,
-                },
-            },
-        );
-
-        dialogRef.afterClosed().subscribe(refresh => {
-            if (refresh) {
-                this.getDashboards();
-            }
-        });
-    }
-
-    openEditDataViewDialog(dashboard: Dashboard) {
-        this.openDataViewModificationDialog(false, dashboard);
-    }
-
-    openDeleteDashboardDialog(dashboard: Dashboard) {
-        this.dashboardService.deleteDashboard(dashboard).subscribe(() => {
-            this.getDashboards();
-        });
-    }
-
-    showDashboard(dashboard: Dashboard) {
-        this.router.navigate(['dataexplorer/', dashboard.elementId]);
-    }
-
-    editDashboard(dashboard: Dashboard) {
-        this.router.navigate(['dataexplorer/', dashboard.elementId], {
-            queryParams: { action: 'edit' },
-        });
-    }
-}
diff --git 
a/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview/data-explorer-dashboard-overview.component.html
 
b/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview/data-explorer-dashboard-overview.component.html
new file mode 100644
index 0000000000..a2eae808fa
--- /dev/null
+++ 
b/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview/data-explorer-dashboard-overview.component.html
@@ -0,0 +1,114 @@
+<!--
+  ~ 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">
+    <sp-basic-header-title-component
+        title="Dashboards"
+    ></sp-basic-header-title-component>
+    <div fxFlex="100" fxLayout="row" fxLayoutAlign="center start">
+        <sp-table
+            fxFlex="90"
+            [columns]="displayedColumns"
+            [dataSource]="dataSource"
+        >
+            <ng-container matColumnDef="name">
+                <th
+                    fxFlex="60"
+                    fxLayoutAlign="start center"
+                    mat-header-cell
+                    *matHeaderCellDef
+                >
+                    Data View
+                </th>
+                <td
+                    fxFlex="60"
+                    fxLayoutAlign="start center"
+                    mat-cell
+                    *matCellDef="let element"
+                >
+                    {{ element.name }}<br />
+                    {{ element.description }}
+                </td>
+            </ng-container>
+
+            <ng-container matColumnDef="actions">
+                <th
+                    fxFlex="40"
+                    fxLayoutAlign="center center"
+                    mat-header-cell
+                    *matHeaderCellDef
+                ></th>
+                <td
+                    fxFlex="40"
+                    fxLayoutAlign="start center"
+                    mat-cell
+                    *matCellDef="let element"
+                >
+                    <div fxLayout="row" fxFlex="100" fxLayoutAlign="end 
center">
+                        <button
+                            mat-icon-button
+                            color="accent"
+                            matTooltip="Show data view"
+                            (click)="showDashboard(element)"
+                        >
+                            <i class="material-icons">visibility</i>
+                        </button>
+                        <button
+                            mat-icon-button
+                            color="accent"
+                            matTooltip="Edit data view"
+                            *ngIf="hasDataExplorerWritePrivileges"
+                            [attr.data-cy]="'edit-dashboard-' + element.name"
+                            (click)="editDashboard(element)"
+                        >
+                            <i class="material-icons">edit</i>
+                        </button>
+                        <button
+                            mat-icon-button
+                            color="accent"
+                            matTooltip="Edit data view settings"
+                            *ngIf="hasDataExplorerWritePrivileges"
+                            (click)="openEditDataViewDialog(element)"
+                        >
+                            <i class="material-icons">settings</i>
+                        </button>
+                        <button
+                            mat-icon-button
+                            color="accent"
+                            matTooltip="Manage permissions"
+                            *ngIf="isAdmin"
+                            (click)="showPermissionsDialog(element)"
+                        >
+                            <i class="material-icons">share</i>
+                        </button>
+                        <button
+                            mat-icon-button
+                            color="accent"
+                            matTooltip="Delete data view"
+                            *ngIf="hasDataExplorerDeletePrivileges"
+                            [attr.data-cy]="'delete-dashboard-' + element.name"
+                            (click)="openDeleteDashboardDialog(element)"
+                        >
+                            <i class="material-icons">delete</i>
+                        </button>
+                    </div>
+                </td>
+            </ng-container>
+        </sp-table>
+    </div>
+</div>
diff --git 
a/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview/data-explorer-dashboard-overview.component.ts
 
b/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview/data-explorer-dashboard-overview.component.ts
new file mode 100644
index 0000000000..a883f94f62
--- /dev/null
+++ 
b/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview/data-explorer-dashboard-overview.component.ts
@@ -0,0 +1,126 @@
+/*
+ * 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 } from '@angular/core';
+import { MatTableDataSource } from '@angular/material/table';
+import {
+    Dashboard,
+    DataViewDataExplorerService,
+} from '@streampipes/platform-services';
+import { ObjectPermissionDialogComponent } from 
'../../../../core-ui/object-permission-dialog/object-permission-dialog.component';
+import {
+    CurrentUserService,
+    DialogService,
+    PanelType,
+} from '@streampipes/shared-ui';
+import { AuthService } from '../../../../services/auth.service';
+import { Router } from '@angular/router';
+import { SpDataExplorerOverviewDirective } from 
'../data-explorer-overview.directive';
+import { DataExplorerDashboardService } from 
'../../../services/data-explorer-dashboard.service';
+
+@Component({
+    selector: 'sp-data-explorer-dashboard-overview',
+    templateUrl: './data-explorer-dashboard-overview.component.html',
+    styleUrls: ['../data-explorer-overview.component.scss'],
+})
+export class SpDataExplorerDashboardOverviewComponent extends 
SpDataExplorerOverviewDirective {
+    dataSource = new MatTableDataSource<Dashboard>();
+    displayedColumns: string[] = [];
+    dashboards: Dashboard[] = [];
+
+    constructor(
+        private dataViewService: DataViewDataExplorerService,
+        private dashboardService: DataViewDataExplorerService,
+        private dataExplorerDashboardService: DataExplorerDashboardService,
+        public dialogService: DialogService,
+        router: Router,
+        authService: AuthService,
+        currentUserService: CurrentUserService,
+    ) {
+        super(dialogService, authService, currentUserService, router);
+    }
+
+    afterInit(): void {
+        this.displayedColumns = ['name', 'actions'];
+        this.getDashboards();
+    }
+
+    showPermissionsDialog(dashboard: Dashboard) {
+        const dialogRef = this.dialogService.open(
+            ObjectPermissionDialogComponent,
+            {
+                panelType: PanelType.SLIDE_IN_PANEL,
+                title: 'Manage permissions',
+                width: '50vw',
+                data: {
+                    objectInstanceId: dashboard.elementId,
+                    headerTitle:
+                        'Manage permissions for dashboard ' + dashboard.name,
+                },
+            },
+        );
+
+        dialogRef.afterClosed().subscribe(refresh => {
+            if (refresh) {
+                this.getDashboards();
+            }
+        });
+    }
+
+    openEditDataViewDialog(dashboard: Dashboard) {
+        const dialogRef =
+            this.dataExplorerDashboardService.openDataViewModificationDialog(
+                false,
+                dashboard,
+            );
+
+        dialogRef.afterClosed().subscribe(() => {
+            this.getDashboards();
+        });
+    }
+
+    openDeleteDashboardDialog(dashboard: Dashboard) {
+        this.dashboardService.deleteDashboard(dashboard).subscribe(() => {
+            this.getDashboards();
+        });
+    }
+
+    showDashboard(dashboard: Dashboard) {
+        this.router.navigate([
+            'dataexplorer',
+            'dashboard',
+            dashboard.elementId,
+        ]);
+    }
+
+    editDashboard(dashboard: Dashboard) {
+        this.router.navigate(
+            ['dataexplorer', 'dashboard', dashboard.elementId],
+            {
+                queryParams: { action: 'edit' },
+            },
+        );
+    }
+
+    getDashboards() {
+        this.dataViewService.getDataViews().subscribe(data => {
+            this.dashboards = data.sort((a, b) => 
a.name.localeCompare(b.name));
+            this.dataSource.data = this.dashboards;
+        });
+    }
+}
diff --git 
a/ui/src/app/data-explorer/components/overview/data-explorer-data-view-overview/data-explorer-data-view-overview.component.html
 
b/ui/src/app/data-explorer/components/overview/data-explorer-data-view-overview/data-explorer-data-view-overview.component.html
new file mode 100644
index 0000000000..d641b1ff7c
--- /dev/null
+++ 
b/ui/src/app/data-explorer/components/overview/data-explorer-data-view-overview/data-explorer-data-view-overview.component.html
@@ -0,0 +1,95 @@
+<!--
+  ~ 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">
+    <sp-basic-header-title-component
+        title="Data Views"
+    ></sp-basic-header-title-component>
+    <div fxFlex="100" fxLayout="row" fxLayoutAlign="center start">
+        <sp-table
+            fxFlex="90"
+            [columns]="displayedColumns"
+            [dataSource]="dataSource"
+        >
+            <ng-container matColumnDef="name">
+                <th
+                    fxFlex="60"
+                    fxLayoutAlign="start center"
+                    mat-header-cell
+                    *matHeaderCellDef
+                >
+                    Data View
+                </th>
+                <td
+                    fxFlex="60"
+                    fxLayoutAlign="start center"
+                    mat-cell
+                    *matCellDef="let element"
+                >
+                    {{ element.baseAppearanceConfig.widgetTitle }}<br />
+                </td>
+            </ng-container>
+
+            <ng-container matColumnDef="actions">
+                <th
+                    fxFlex="40"
+                    fxLayoutAlign="center center"
+                    mat-header-cell
+                    *matHeaderCellDef
+                ></th>
+                <td
+                    fxFlex="40"
+                    fxLayoutAlign="start center"
+                    mat-cell
+                    *matCellDef="let element"
+                >
+                    <div fxLayout="row" fxFlex="100" fxLayoutAlign="end 
center">
+                        <button
+                            mat-icon-button
+                            color="accent"
+                            matTooltip="Show data view"
+                            (click)="openDataView(element, false)"
+                        >
+                            <i class="material-icons">visibility</i>
+                        </button>
+                        <button
+                            mat-icon-button
+                            color="accent"
+                            matTooltip="Edit data view"
+                            *ngIf="hasDataExplorerWritePrivileges"
+                            [attr.data-cy]="'edit-dashboard-' + element.name"
+                            (click)="openDataView(element, true)"
+                        >
+                            <i class="material-icons">edit</i>
+                        </button>
+                        <button
+                            mat-icon-button
+                            color="accent"
+                            matTooltip="Delete data view"
+                            *ngIf="hasDataExplorerDeletePrivileges"
+                            [attr.data-cy]="'delete-dashboard-' + element.name"
+                            (click)="deleteDataView(element)"
+                        >
+                            <i class="material-icons">delete</i>
+                        </button>
+                    </div>
+                </td>
+            </ng-container>
+        </sp-table>
+    </div>
+</div>
diff --git 
a/ui/src/app/data-explorer/components/overview/data-explorer-data-view-overview/data-explorer-data-view-overview.component.ts
 
b/ui/src/app/data-explorer/components/overview/data-explorer-data-view-overview/data-explorer-data-view-overview.component.ts
new file mode 100644
index 0000000000..277ef2b5cf
--- /dev/null
+++ 
b/ui/src/app/data-explorer/components/overview/data-explorer-data-view-overview/data-explorer-data-view-overview.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 } from '@angular/core';
+import { SpDataExplorerOverviewDirective } from 
'../data-explorer-overview.directive';
+import { MatTableDataSource } from '@angular/material/table';
+import {
+    Dashboard,
+    DataExplorerWidgetModel,
+    DataViewDataExplorerService,
+} from '@streampipes/platform-services';
+import { CurrentUserService, DialogService } from '@streampipes/shared-ui';
+import { Router } from '@angular/router';
+import { AuthService } from '../../../../services/auth.service';
+
+@Component({
+    selector: 'sp-data-explorer-data-view-overview',
+    templateUrl: './data-explorer-data-view-overview.component.html',
+    styleUrls: ['../data-explorer-overview.component.scss'],
+})
+export class SpDataExplorerDataViewOverviewComponent extends 
SpDataExplorerOverviewDirective {
+    dataSource = new MatTableDataSource<DataExplorerWidgetModel>();
+    displayedColumns: string[] = [];
+    dashboards: Dashboard[] = [];
+
+    constructor(
+        private dataViewService: DataViewDataExplorerService,
+        public dialogService: DialogService,
+        authService: AuthService,
+        currentUserService: CurrentUserService,
+        router: Router,
+    ) {
+        super(dialogService, authService, currentUserService, router);
+    }
+
+    afterInit(): void {
+        this.displayedColumns = ['name', 'actions'];
+        this.getCharts();
+    }
+
+    getCharts(): void {
+        this.dataViewService.getAllWidgets().subscribe(widgets => {
+            widgets = widgets.sort((a, b) =>
+                a.baseAppearanceConfig.widgetTitle.localeCompare(
+                    b.baseAppearanceConfig.widgetTitle,
+                ),
+            );
+            this.dataSource.data = widgets;
+        });
+    }
+
+    openDataView(dataView: DataExplorerWidgetModel, editMode: boolean): void {
+        this.router.navigate(
+            ['dataexplorer', 'data-view', dataView.elementId],
+            { queryParams: { editMode } },
+        );
+    }
+
+    deleteDataView(dataView: DataExplorerWidgetModel) {
+        this.dataViewService.deleteWidget(dataView.elementId);
+    }
+}
diff --git 
a/ui/src/app/data-explorer/components/overview/data-explorer-overview.component.html
 
b/ui/src/app/data-explorer/components/overview/data-explorer-overview.component.html
new file mode 100644
index 0000000000..6154c47c45
--- /dev/null
+++ 
b/ui/src/app/data-explorer/components/overview/data-explorer-overview.component.html
@@ -0,0 +1,56 @@
+<!--
+  ~ 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="open-new-data-view-dialog"
+            (click)="openNewDashboardDialog()"
+            class="mr-10"
+            *ngIf="hasDataExplorerWritePrivileges"
+        >
+            <i class="material-icons">add</i>
+            <span>New Dashboard</span>
+        </button>
+        <button
+            mat-button
+            mat-raised-button
+            color="accent"
+            data-cy="open-new-data-view-dialog"
+            (click)="createNewDataView()"
+            class="mr-10"
+            *ngIf="hasDataExplorerWritePrivileges"
+        >
+            <i class="material-icons">add</i>
+            <span>New Data View</span>
+        </button>
+    </div>
+    <div fxFlex="100" fxLayout="column">
+        
<sp-data-explorer-dashboard-overview></sp-data-explorer-dashboard-overview>
+        
<sp-data-explorer-data-view-overview></sp-data-explorer-data-view-overview>
+    </div>
+</sp-basic-view>
diff --git 
a/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.scss
 
b/ui/src/app/data-explorer/components/overview/data-explorer-overview.component.scss
similarity index 100%
rename from 
ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.scss
rename to 
ui/src/app/data-explorer/components/overview/data-explorer-overview.component.scss
diff --git 
a/ui/src/app/data-explorer/components/overview/data-explorer-overview.component.ts
 
b/ui/src/app/data-explorer/components/overview/data-explorer-overview.component.ts
new file mode 100644
index 0000000000..151daee106
--- /dev/null
+++ 
b/ui/src/app/data-explorer/components/overview/data-explorer-overview.component.ts
@@ -0,0 +1,85 @@
+/*
+ * 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, ViewChild } from '@angular/core';
+import { Dashboard } from '@streampipes/platform-services';
+import {
+    CurrentUserService,
+    DialogService,
+    SpBreadcrumbService,
+} from '@streampipes/shared-ui';
+import { AuthService } from '../../../services/auth.service';
+import { SpDataExplorerRoutes } from '../../data-explorer.routes';
+import { DataExplorerDashboardService } from 
'../../services/data-explorer-dashboard.service';
+import { SpDataExplorerDashboardOverviewComponent } from 
'./data-explorer-dashboard-overview/data-explorer-dashboard-overview.component';
+import { SpDataExplorerOverviewDirective } from 
'./data-explorer-overview.directive';
+import { Router } from '@angular/router';
+
+@Component({
+    selector: 'sp-data-explorer-overview',
+    templateUrl: './data-explorer-overview.component.html',
+    styleUrls: ['./data-explorer-overview.component.scss'],
+})
+export class DataExplorerOverviewComponent extends 
SpDataExplorerOverviewDirective {
+    @ViewChild(SpDataExplorerDashboardOverviewComponent)
+    dashboardOverview: SpDataExplorerDashboardOverviewComponent;
+
+    constructor(
+        public dialogService: DialogService,
+        private breadcrumbService: SpBreadcrumbService,
+        private dataExplorerDashboardService: DataExplorerDashboardService,
+        authService: AuthService,
+        currentUserService: CurrentUserService,
+        router: Router,
+    ) {
+        super(dialogService, authService, currentUserService, router);
+    }
+
+    afterInit(): void {
+        this.breadcrumbService.updateBreadcrumb(
+            this.breadcrumbService.getRootLink(SpDataExplorerRoutes.BASE),
+        );
+    }
+
+    openNewDashboardDialog() {
+        const dataViewDashboard: Dashboard = {};
+        dataViewDashboard.dashboardGeneralSettings = {};
+        dataViewDashboard.widgets = [];
+        dataViewDashboard.name = '';
+
+        this.openDataViewModificationDialog(true, dataViewDashboard);
+    }
+
+    createNewDataView(): void {
+        this.router.navigate(['dataexplorer', 'data-view'], {
+            queryParams: { editMode: true },
+        });
+    }
+
+    openDataViewModificationDialog(createMode: boolean, dashboard: Dashboard) {
+        const dialogRef =
+            this.dataExplorerDashboardService.openDataViewModificationDialog(
+                createMode,
+                dashboard,
+            );
+
+        dialogRef.afterClosed().subscribe(() => {
+            this.dashboardOverview.getDashboards();
+        });
+    }
+}
diff --git 
a/ui/src/app/data-explorer/components/overview/data-explorer-overview.directive.ts
 
b/ui/src/app/data-explorer/components/overview/data-explorer-overview.directive.ts
new file mode 100644
index 0000000000..909bf51903
--- /dev/null
+++ 
b/ui/src/app/data-explorer/components/overview/data-explorer-overview.directive.ts
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Directive, OnDestroy, OnInit } from '@angular/core';
+import { Subscription } from 'rxjs';
+import { UserPrivilege } from '../../../_enums/user-privilege.enum';
+import { UserRole } from '../../../_enums/user-role.enum';
+import { CurrentUserService, DialogService } from '@streampipes/shared-ui';
+import { AuthService } from '../../../services/auth.service';
+import { Router } from '@angular/router';
+
+@Directive()
+export abstract class SpDataExplorerOverviewDirective
+    implements OnInit, OnDestroy
+{
+    isAdmin = false;
+
+    public hasDataExplorerWritePrivileges = false;
+    public hasDataExplorerDeletePrivileges = false;
+
+    authSubscription: Subscription;
+
+    protected constructor(
+        public dialogService: DialogService,
+        protected authService: AuthService,
+        protected currentUserService: CurrentUserService,
+        protected router: Router,
+    ) {}
+
+    ngOnInit() {
+        this.authSubscription = this.currentUserService.user$.subscribe(
+            user => {
+                this.hasDataExplorerWritePrivileges = this.authService.hasRole(
+                    UserPrivilege.PRIVILEGE_WRITE_DATA_EXPLORER_VIEW,
+                );
+                this.hasDataExplorerDeletePrivileges = 
this.authService.hasRole(
+                    UserPrivilege.PRIVILEGE_DELETE_DATA_EXPLORER_VIEW,
+                );
+                this.isAdmin = user.roles.indexOf(UserRole.ROLE_ADMIN) > -1;
+                this.afterInit();
+            },
+        );
+    }
+
+    abstract afterInit(): void;
+
+    ngOnDestroy() {
+        this.authSubscription?.unsubscribe();
+    }
+}
diff --git a/ui/src/app/data-explorer/data-explorer.module.ts 
b/ui/src/app/data-explorer/data-explorer.module.ts
index 6d31754b25..44b8ab9baf 100644
--- a/ui/src/app/data-explorer/data-explorer.module.ts
+++ b/ui/src/app/data-explorer/data-explorer.module.ts
@@ -37,7 +37,7 @@ import { ColorPickerModule } from 'ngx-color-picker';
 import { PlatformServicesModule } from '@streampipes/platform-services';
 import { CoreUiModule } from '../core-ui/core-ui.module';
 import { DataExplorerDashboardGridComponent } from 
'./components/widget-view/grid-view/data-explorer-dashboard-grid.component';
-import { DataExplorerDashboardOverviewComponent } from 
'./components/overview/data-explorer-dashboard-overview.component';
+import { DataExplorerOverviewComponent } from 
'./components/overview/data-explorer-overview.component';
 import { DataExplorerDashboardPanelComponent } from 
'./components/panel/data-explorer-dashboard-panel.component';
 import { TimeRangeSelectorComponent } from 
'./components/time-selector/timeRangeSelector.component';
 import { DataExplorerDashboardWidgetComponent } from 
'./components/widget/data-explorer-dashboard-widget.component';
@@ -113,6 +113,10 @@ import { MatTooltipModule } from 
'@angular/material/tooltip';
 import { MatProgressBarModule } from '@angular/material/progress-bar';
 import { MatButtonToggleModule } from '@angular/material/button-toggle';
 import { SpImageContainerComponent } from 
'./components/widgets/image/image-container/image-container.component';
+import { SpDataExplorerDataViewOverviewComponent } from 
'./components/overview/data-explorer-data-view-overview/data-explorer-data-view-overview.component';
+import { SpDataExplorerDashboardOverviewComponent } from 
'./components/overview/data-explorer-dashboard-overview/data-explorer-dashboard-overview.component';
+import { DataExplorerDataViewComponent } from 
'./components/data-view/data-explorer-data-view.component';
+import { DataExplorerDataViewToolbarComponent } from 
'./components/data-view/data-view-toolbar/data-explorer-data-view-toolbar.component';
 
 @NgModule({
     imports: [
@@ -167,15 +171,23 @@ import { SpImageContainerComponent } from 
'./components/widgets/image/image-cont
                 children: [
                     {
                         path: '',
-                        component: DataExplorerDashboardOverviewComponent,
+                        component: DataExplorerOverviewComponent,
                     },
                     {
-                        path: ':id',
+                        path: 'data-view',
+                        component: DataExplorerDataViewComponent,
+                    },
+                    {
+                        path: 'data-view/:id',
+                        component: DataExplorerDataViewComponent,
+                    },
+                    {
+                        path: 'dashboard/:id',
                         component: DataExplorerDashboardPanelComponent,
                         canDeactivate: [DataExplorerPanelCanDeactivateGuard],
                     },
                     {
-                        path: ':id/:startTime/:endTime',
+                        path: 'dashboard/:id/:startTime/:endTime',
                         component: DataExplorerDashboardPanelComponent,
                         canDeactivate: [DataExplorerPanelCanDeactivateGuard],
                     },
@@ -186,7 +198,7 @@ import { SpImageContainerComponent } from 
'./components/widgets/image/image-cont
     declarations: [
         AggregateConfigurationComponent,
         DataExplorerDashboardGridComponent,
-        DataExplorerDashboardOverviewComponent,
+        DataExplorerOverviewComponent,
         DataExplorerDashboardPanelComponent,
         DataExplorerDashboardSlideViewComponent,
         DataExplorerDashboardWidgetComponent,
@@ -194,6 +206,8 @@ import { SpImageContainerComponent } from 
'./components/widgets/image/image-cont
         DataExplorerEditDataViewDialogComponent,
         DataExplorerWidgetAppearanceSettingsComponent,
         DataExplorerWidgetDataSettingsComponent,
+        DataExplorerDataViewComponent,
+        DataExplorerDataViewToolbarComponent,
         CorrelationWidgetConfigComponent,
         FieldSelectionPanelComponent,
         FieldSelectionComponent,
@@ -222,6 +236,8 @@ import { SpImageContainerComponent } from 
'./components/widgets/image/image-cont
         DataExplorerVisualisationSettingsComponent,
         WidgetDirective,
         TooMuchDataComponent,
+        SpDataExplorerDataViewOverviewComponent,
+        SpDataExplorerDashboardOverviewComponent,
         SpEchartsWidgetComponent,
         SpValueHeatmapWidgetConfigComponent,
         SpHistogramChartWidgetConfigComponent,
diff --git 
a/ui/src/app/data-explorer/services/data-explorer-dashboard.service.ts 
b/ui/src/app/data-explorer/services/data-explorer-dashboard.service.ts
new file mode 100644
index 0000000000..aefed314e1
--- /dev/null
+++ b/ui/src/app/data-explorer/services/data-explorer-dashboard.service.ts
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Injectable } from '@angular/core';
+import { Dashboard } from '@streampipes/platform-services';
+import { DataExplorerEditDataViewDialogComponent } from 
'../dialogs/edit-dashboard/data-explorer-edit-data-view-dialog.component';
+import { DialogService, PanelType } from '@streampipes/shared-ui';
+
+@Injectable({ providedIn: 'root' })
+export class DataExplorerDashboardService {
+    constructor(private dialogService: DialogService) {}
+
+    openDataViewModificationDialog(createMode: boolean, dashboard: Dashboard) {
+        return this.dialogService.open(
+            DataExplorerEditDataViewDialogComponent,
+            {
+                panelType: PanelType.STANDARD_PANEL,
+                title: createMode ? 'New Data View' : 'Edit Data View',
+                width: '70vw',
+                data: {
+                    createMode: createMode,
+                    dashboard: dashboard,
+                },
+            },
+        );
+    }
+}

Reply via email to