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 2024/07/22 15:10:43 UTC

(streampipes) branch 3032-harmonize-data-explorer-and-live-dashboard updated: feat(#3043): Add data view selection to data explorer dashboard (#3044)

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

riemer pushed a commit to branch 3032-harmonize-data-explorer-and-live-dashboard
in repository https://gitbox.apache.org/repos/asf/streampipes.git


The following commit(s) were added to refs/heads/3032-harmonize-data-explorer-and-live-dashboard by this push:
     new 01c6320e67 feat(#3043): Add data view selection to data explorer dashboard (#3044)
01c6320e67 is described below

commit 01c6320e673dcb5d02f45c1b9a2d632e253b3596
Author: Dominik Riemer <do...@gmail.com>
AuthorDate: Mon Jul 22 17:10:38 2024 +0200

    feat(#3043): Add data view selection to data explorer dashboard (#3044)
    
    * feat(#3043): Add data view selection to data explorer dashboard
    
    * Add routing service
    
    * Fix cypress tests and modify routing
---
 .../support/utils/DataDownloadDialogUtils.ts       |   2 +-
 ui/cypress/support/utils/datalake/DataLakeUtils.ts |  59 ++++--
 .../dataDownloadDialogTest.smoke.spec.ts           |   6 +-
 ui/cypress/tests/datalake/deleteWidget.ts          |  31 +--
 .../datalake/widgetDataConfiguration.smoke.spec.ts |   6 +-
 .../dashboard-toolbar.component.html               | 130 ++++++++++++
 .../dashboard-toolbar.component.scss}              |  11 +-
 .../dashboard-toolbar.component.ts}                |  35 +++-
 ...dashboard-widget-selection-panel.component.html |  44 ++++
 ...ashboard-widget-selection-panel.component.scss} |   2 +-
 .../dashboard-widget-selection-panel.component.ts} |  52 ++---
 .../data-view-preview.component.html               |  52 +++++
 .../data-view-preview.component.scss}              |  18 +-
 .../data-view-preview.component.ts                 |  44 ++++
 .../data-view-selection.component.html             |  27 +++
 .../data-view-selection.component.scss}            |   6 +-
 .../data-view-selection.component.ts               |  47 +++++
 .../data-explorer-dashboard-panel.component.html   | 105 ++++++++++
 .../data-explorer-dashboard-panel.component.scss   |  11 +-
 .../data-explorer-dashboard-panel.component.ts     | 179 ++--------------
 .../data-explorer-data-view.component.html         |   3 +
 .../data-view/data-explorer-data-view.component.ts |  53 +++--
 ...lorer-widget-appearance-settings.component.html |   1 +
 ...lorer-widget-appearance-settings.component.scss |   0
 ...xplorer-widget-appearance-settings.component.ts |   6 +-
 .../data-explorer-designer-panel.component.html    |   0
 .../data-explorer-designer-panel.component.scss    |   3 +-
 .../data-explorer-designer-panel.component.ts      |   2 +-
 ...ta-explorer-widget-data-settings.component.html |   0
 ...ta-explorer-widget-data-settings.component.scss |   0
 ...data-explorer-widget-data-settings.component.ts |   4 +-
 .../field-selection-panel.component.html           |   0
 .../field-selection-panel.component.scss           |   0
 .../field-selection-panel.component.ts             |   4 +-
 .../field-selection/field-selection.component.html |   0
 .../field-selection/field-selection.component.scss |   0
 .../field-selection/field-selection.component.ts   |   2 +-
 .../filter-selection-panel.component.html          |   0
 .../filter-selection-panel.component.scss          |   0
 .../filter-selection-panel.component.ts            |   4 +-
 .../group-selection-panel.component.html           |   0
 .../group-selection-panel.component.scss           |   0
 .../group-selection-panel.component.ts             |   4 +-
 ...-explorer-visualisation-settings.component.html |   0
 ...-explorer-visualisation-settings.component.scss |   0
 ...ta-explorer-visualisation-settings.component.ts |   6 +-
 .../data-explorer-data-view-toolbar.component.html |  23 ++-
 .../data-explorer-data-view-toolbar.component.ts   |   6 +
 ...data-explorer-dashboard-overview.component.html |   2 +-
 .../data-explorer-dashboard-overview.component.ts  |  19 +-
 ...data-explorer-data-view-overview.component.html |  13 +-
 .../data-explorer-data-view-overview.component.ts  |  11 +-
 .../overview/data-explorer-overview.component.html |   3 +-
 .../overview/data-explorer-overview.component.ts   |  10 +-
 .../overview/data-explorer-overview.directive.ts   |   4 +-
 .../data-explorer-dashboard-panel.component.html   | 230 ---------------------
 .../widget-view/abstract-widget-view.directive.ts  |  20 +-
 .../data-explorer-dashboard-grid.component.html    |   3 -
 ...ta-explorer-dashboard-slide-view.component.html |   3 -
 ...data-explorer-dashboard-slide-view.component.ts |   6 -
 .../data-explorer-dashboard-widget.component.html  |  31 +--
 .../data-explorer-dashboard-widget.component.ts    |  56 ++---
 .../data-explorer-panel.can-deactivate.guard.ts    |   8 +-
 ui/src/app/data-explorer/data-explorer.module.ts   |  26 ++-
 .../services/data-explorer-dashboard.service.ts    |  28 ++-
 .../services/data-explorer-routing.service.ts      |  93 +++++++++
 66 files changed, 883 insertions(+), 671 deletions(-)

diff --git a/ui/cypress/support/utils/DataDownloadDialogUtils.ts b/ui/cypress/support/utils/DataDownloadDialogUtils.ts
index ba8f1ec9b4..04ce651078 100644
--- a/ui/cypress/support/utils/DataDownloadDialogUtils.ts
+++ b/ui/cypress/support/utils/DataDownloadDialogUtils.ts
@@ -34,7 +34,7 @@ export class DataDownloadDialogUtils {
         DataLakeUtils.editDataView(dataViewName);
 
         // select download button
-        cy.dataCy('download-prepared_data-table').click();
+        cy.dataCy('data-view-data-download-btn').click();
 
         // download-customInterval, download-all, download-visible
         cy.dataCy(
diff --git a/ui/cypress/support/utils/datalake/DataLakeUtils.ts b/ui/cypress/support/utils/datalake/DataLakeUtils.ts
index 41fadcf9b0..dd52f048e4 100644
--- a/ui/cypress/support/utils/datalake/DataLakeUtils.ts
+++ b/ui/cypress/support/utils/datalake/DataLakeUtils.ts
@@ -99,9 +99,12 @@ export class DataLakeUtils {
         // DataLakeUtils.addNewWidget();
         DataLakeUtils.selectDataSet(dataSet);
         DataLakeUtils.dataConfigSelectAllFields();
+
+        DataLakeUtils.selectAppearanceConfig();
+        DataLakeUtils.selectDataViewName(dataViewName);
+
         DataLakeUtils.openVisualizationConfig();
         DataLakeUtils.selectVisualizationType(widgetType);
-        DataLakeUtils.clickCreateButton();
 
         cy.wait(1000);
     }
@@ -132,29 +135,52 @@ export class DataLakeUtils {
         PrepareTestDataUtils.loadDataIntoDataLake('fileTest/random.csv');
     }
 
-    public static createAndEditDataView(name: string) {
+    public static createAndEditDashboard(name: string) {
         // Create new data view
-        cy.dataCy('open-new-data-view-dialog').click();
+        cy.dataCy('open-new-dashboard-dialog').click();
 
         // Configure data view
         cy.dataCy('data-view-name').type(name);
         cy.dataCy('save-data-view').click();
 
-        this.editDataView(name);
+        this.editDashboard(name);
+    }
+
+    public static addDataViewToDashboard(dataViewName: string) {
+        this.selectTimeRange(
+            new Date(2020, 10, 20, 22, 44),
+            this.getFutureDate(),
+        );
+        cy.dataCy('add-data-view-btn-' + dataViewName).click();
+    }
+
+    public static createAndEditDataView(name: string) {
+        // Create new data view
+        cy.dataCy('open-new-data-view').click();
     }
 
-    public static removeWidget(widgetName: string) {
-        cy.dataCy('remove-' + widgetName).click();
+    public static removeWidget(dataViewName: string) {
+        cy.dataCy('remove-' + dataViewName).click();
+    }
+
+    public static editDashboard(dashboardName: string) {
+        // Click edit button
+        // following only works if single view is available
+        cy.dataCy('edit-dashboard-' + dashboardName).click();
     }
 
     public static editDataView(dataViewName: string) {
         // Click edit button
         // following only works if single view is available
-        cy.dataCy('edit-dashboard-' + dataViewName).click();
+        cy.dataCy('edit-data-view-' + dataViewName).click();
+    }
+
+    public static saveDataViewConfiguration() {
+        cy.dataCy('save-data-view-btn', { timeout: 10000 }).click();
     }
 
-    public static saveDataExplorerWidgetConfiguration() {
-        cy.dataCy('save-data-explorer-widget-btn', { timeout: 10000 }).click();
+    public static saveDashboardConfiguration() {
+        cy.dataCy('save-dashboard-btn', { timeout: 10000 }).click();
     }
 
     public static editWidget(widgetName: string) {
@@ -167,12 +193,17 @@ export class DataLakeUtils {
     }
 
     public static saveAndReEditWidget(dataViewName: string) {
-        // Save configuration
-        DataLakeUtils.saveDataExplorerWidgetConfiguration();
-        DataLakeUtils.goBackToOverview();
+        // Save data view configuration
+        DataLakeUtils.saveDataViewConfiguration();
         DataLakeUtils.editDataView(dataViewName);
     }
 
+    public static saveAndReEditDashboard(dashboardName: string) {
+        // Save dashboard configuration
+        DataLakeUtils.saveDashboardConfiguration();
+        DataLakeUtils.editDashboard(dashboardName);
+    }
+
     public static clickTab(tabName: string) {
         // Click start tab to go to overview
         cy.get('div').contains(tabName).parent().click();
@@ -277,6 +308,10 @@ export class DataLakeUtils {
         cy.get('.mdc-tab__text-label').contains('Appearance').parent().click();
     }
 
+    public static selectDataViewName(dataViewName: string) {
+        cy.dataCy('appearance-config-widget-title').clear().type(dataViewName);
+    }
+
     public static clickCreateButton() {
         // Create widget
         cy.dataCy('data-explorer-select-data-set-create-btn').click();
diff --git a/ui/cypress/tests/dataDownloadDialog/dataDownloadDialogTest.smoke.spec.ts b/ui/cypress/tests/dataDownloadDialog/dataDownloadDialogTest.smoke.spec.ts
index 574509e074..29f7b79e74 100644
--- a/ui/cypress/tests/dataDownloadDialog/dataDownloadDialogTest.smoke.spec.ts
+++ b/ui/cypress/tests/dataDownloadDialog/dataDownloadDialogTest.smoke.spec.ts
@@ -21,7 +21,7 @@ import { DataDownloadDialogUtils } from '../../support/utils/DataDownloadDialogU
 import { DataLakeUtils } from '../../support/utils/datalake/DataLakeUtils';
 import { PrepareTestDataUtils } from '../../support/utils/PrepareTestDataUtils';
 
-describe('Test live data download dialog', () => {
+describe('Test data explorer data download dialog', () => {
     before('Setup Test', () => {
         cy.initStreamPipesTest();
         PrepareTestDataUtils.loadDataIntoDataLake(
@@ -30,7 +30,7 @@ describe('Test live data download dialog', () => {
         );
 
         DataLakeUtils.addDataViewAndTableWidget(dataViewName, 'Persist');
-        DataLakeUtils.saveDataExplorerWidgetConfiguration();
+        DataLakeUtils.saveDataViewConfiguration();
     });
 
     beforeEach('Setup Test', () => {
@@ -38,7 +38,7 @@ describe('Test live data download dialog', () => {
         cy.login();
     });
 
-    const dataViewName = 'TestView';
+    const dataViewName = 'NewWidget';
 
     const formatTestsExportConfig: ExportConfig = {
         formatExportConfig: undefined,
diff --git a/ui/cypress/tests/datalake/deleteWidget.ts b/ui/cypress/tests/datalake/deleteWidget.ts
index 2de896dcd4..2d9da9a910 100644
--- a/ui/cypress/tests/datalake/deleteWidget.ts
+++ b/ui/cypress/tests/datalake/deleteWidget.ts
@@ -28,37 +28,42 @@ describe('Test Table View in Data Explorer', () => {
          * Prepare tests
          */
         DataLakeUtils.addDataViewAndTableWidget('TestView', 'Persist');
+        DataLakeUtils.saveDataViewConfiguration();
+        DataLakeUtils.createAndEditDashboard('TestDashboard');
+        DataLakeUtils.addDataViewToDashboard('TestView');
 
         // Check that widget is visible
-        cy.dataCy('widget-datalake_configuration', { timeout: 10000 }).should(
-            'be.visible',
-        );
+        cy.dataCy('widget-TestView', { timeout: 10000 }).should('be.visible');
 
         // Activate edit mode
-        DataLakeUtils.saveAndReEditWidget('TestView');
+        DataLakeUtils.saveAndReEditDashboard('TestDashboard');
 
         // Delete widget
-        DataLakeUtils.removeWidget('datalake_configuration');
+        DataLakeUtils.removeWidget('TestView');
 
         // Save dashboard
-        DataLakeUtils.saveDataExplorerWidgetConfiguration();
+        DataLakeUtils.saveDashboardConfiguration();
+
+        // Go back to dashboard
+        DataLakeUtils.saveAndReEditDashboard('TestDashboard');
 
         // Check that widget is gone
         cy.dataCy('widget-datalake_configuration', { timeout: 10000 }).should(
             'not.exist',
         );
 
-        // Delete Dashboard
-        // DataLakeUtils.clickStartTab();
-
-        // Check that dashboard is gone
+        DataLakeUtils.goBackToOverview();
 
-        cy.dataCy('delete-dashboard-TestView', { timeout: 10000 }).should(
+        cy.dataCy('delete-dashboard-TestDashboard', { timeout: 10000 }).should(
             'have.length',
             1,
         );
-        cy.dataCy('delete-dashboard-TestView', { timeout: 10000 }).click();
-        cy.dataCy('delete-dashboard-TestView', { timeout: 10000 }).should(
+
+        // Delete dashboard
+        cy.dataCy('delete-dashboard-TestDashboard', { timeout: 10000 }).click();
+
+        // Check that dashboard is gone
+        cy.dataCy('delete-dashboard-TestDashboard', { timeout: 10000 }).should(
             'have.length',
             0,
         );
diff --git a/ui/cypress/tests/datalake/widgetDataConfiguration.smoke.spec.ts b/ui/cypress/tests/datalake/widgetDataConfiguration.smoke.spec.ts
index 0568f70f5e..040bc3cefc 100644
--- a/ui/cypress/tests/datalake/widgetDataConfiguration.smoke.spec.ts
+++ b/ui/cypress/tests/datalake/widgetDataConfiguration.smoke.spec.ts
@@ -30,7 +30,7 @@ describe('Test Table View in Data Explorer', () => {
         /**
          * Prepare tests
          */
-        DataLakeUtils.addDataViewAndTableWidget('TestView', 'Persist');
+        DataLakeUtils.addDataViewAndTableWidget('NewWidget', 'Persist');
 
         // Validate that X lines are available
         DataLakeWidgetTableUtils.checkRows(10);
@@ -72,7 +72,7 @@ describe('Test Table View in Data Explorer', () => {
         DataLakeUtils.dataConfigAddFilter(filterConfig);
         DataLakeUtils.checkIfFilterIsSet(1);
         DataLakeWidgetTableUtils.checkRows(4);
-        DataLakeUtils.saveAndReEditWidget('TestView');
+        DataLakeUtils.saveAndReEditWidget('NewWidget');
         DataLakeUtils.checkIfFilterIsSet(1);
         DataLakeWidgetTableUtils.checkRows(4);
         DataLakeUtils.dataConfigRemoveFilter();
@@ -90,7 +90,7 @@ describe('Test Table View in Data Explorer', () => {
             .last({ timeout: 10000 })
             .contains('c', { timeout: 10000 });
         DataLakeWidgetTableUtils.checkRows(10);
-        DataLakeUtils.saveAndReEditWidget('TestView');
+        DataLakeUtils.saveAndReEditWidget('NewWidget');
         cy.dataCy('data-explorer-group-by-randomtext')
             .find('input')
             .should('be.checked');
diff --git a/ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/dashboard-toolbar.component.html b/ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/dashboard-toolbar.component.html
new file mode 100644
index 0000000000..ff1b2ee7b6
--- /dev/null
+++ b/ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/dashboard-toolbar.component.html
@@ -0,0 +1,130 @@
+<!--
+  ~ 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="data-explorer-options-item"
+    fxLayoutAlign="start center"
+    fxLayout="row"
+    *ngIf="editMode"
+>
+    <button
+        mat-raised-button
+        color="accent"
+        matTooltip="Save"
+        class="edit-menu-btn"
+        (click)="saveDashboardEmitter.emit()"
+        data-cy="save-dashboard-btn"
+    >
+        <mat-icon>save</mat-icon>
+        <span>Save</span>
+    </button>
+    <button
+        mat-raised-button
+        color="accent"
+        matTooltip="Discard"
+        class="mat-basic mr-10 edit-menu-btn"
+        (click)="discardDashboardEmitter.emit()"
+    >
+        <i class="material-icons">undo</i>
+        <span>&nbsp;Discard</span>
+    </button>
+</div>
+<div
+    class="data-explorer-options-item"
+    fxLayoutAlign="start center"
+    fxLayout="row"
+>
+    <button
+        mat-icon-button
+        [matMenuTriggerFor]="menu"
+        aria-label="View mode"
+        matTooltip="View mode"
+    >
+        <mat-icon
+            >{{ viewMode === 'grid' ? 'grid_view' : 'web_asset' }}
+        </mat-icon>
+    </button>
+    <mat-menu #menu="matMenu">
+        <button mat-menu-item (click)="viewModeChange.emit('grid')">
+            <mat-icon>grid_view</mat-icon>
+            <span>Grid</span>
+        </button>
+        <button mat-menu-item (click)="viewModeChange.emit('slide')">
+            <mat-icon>web_asset</mat-icon>
+            <span>Slides</span>
+        </button>
+    </mat-menu>
+</div>
+<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>
+
+    <button
+        mat-icon-button
+        [matMenuTriggerFor]="optMenu"
+        aria-label="Options"
+        data-cy="options-data-explorer"
+    >
+        <mat-icon>more_vert</mat-icon>
+    </button>
+    <mat-menu #optMenu="matMenu">
+        <button
+            mat-menu-item
+            (click)="triggerEditModeEmitter.emit()"
+            *ngIf="!editMode && hasDataExplorerWritePrivileges"
+            data-cy="options-edit-dashboard"
+        >
+            <mat-icon>edit</mat-icon>
+            <span>Edit dashboard</span>
+        </button>
+        <button
+            mat-menu-item
+            (click)="timeRangeVisible = true"
+            *ngIf="!editMode && !timeRangeVisible"
+        >
+            <mat-icon>alarm_on</mat-icon>
+            <span>Show time range selector</span>
+        </button>
+        <button
+            mat-menu-item
+            (click)="timeRangeVisible = false"
+            *ngIf="!editMode && timeRangeVisible"
+        >
+            <mat-icon>alarm_off</mat-icon>
+            <span>Hide time range selector</span>
+        </button>
+        <button
+            mat-menu-item
+            *ngIf="hasDataExplorerDeletePrivileges"
+            (click)="deleteDashboardEmitter.emit()"
+        >
+            <mat-icon>clear</mat-icon>
+            <span>Delete dashboard</span>
+        </button>
+    </mat-menu>
+</div>
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection/field-selection.component.scss b/ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/dashboard-toolbar.component.scss
similarity index 86%
copy from ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection/field-selection.component.scss
copy to ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/dashboard-toolbar.component.scss
index 7dffaf1d04..e9e5de91bb 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection/field-selection.component.scss
+++ b/ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/dashboard-toolbar.component.scss
@@ -1,4 +1,4 @@
-/*
+/*!
  * 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.
@@ -16,6 +16,11 @@
  *
  */
 
-.mat-mdc-form-field.aggregation-width {
-    width: 100px;
+.data-explorer-options {
+    padding: 0;
+}
+
+.data-explorer-options-item {
+    display: inline;
+    margin-right: 10px;
 }
diff --git a/ui/src/app/data-explorer/components/data-view/data-view-toolbar/data-explorer-data-view-toolbar.component.ts b/ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/dashboard-toolbar.component.ts
similarity index 57%
copy from ui/src/app/data-explorer/components/data-view/data-view-toolbar/data-explorer-data-view-toolbar.component.ts
copy to ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/dashboard-toolbar.component.ts
index 37295d4769..e2da2c238d 100644
--- a/ui/src/app/data-explorer/components/data-view/data-view-toolbar/data-explorer-data-view-toolbar.component.ts
+++ b/ui/src/app/data-explorer/components/dashboard/dashboard-toolbar/dashboard-toolbar.component.ts
@@ -20,20 +20,43 @@ import { Component, EventEmitter, Input, Output } from '@angular/core';
 import { TimeSettings } from '@streampipes/platform-services';
 
 @Component({
-    selector: 'sp-data-explorer-data-view-toolbar',
-    templateUrl: './data-explorer-data-view-toolbar.component.html',
+    selector: 'sp-data-explorer-dashboard-toolbar',
+    templateUrl: './dashboard-toolbar.component.html',
+    styleUrls: ['./dashboard-toolbar.component.scss'],
 })
-export class DataExplorerDataViewToolbarComponent {
+export class DataExplorerDashboardToolbarComponent {
     @Input()
-    editMode = true;
+    editMode: boolean;
+
+    @Input()
+    viewMode: string;
+
+    @Input()
+    timeRangeVisible: boolean;
+
+    @Input()
+    hasDataExplorerWritePrivileges: boolean;
+
+    @Input()
+    hasDataExplorerDeletePrivileges: boolean;
 
     @Input()
     timeSettings: TimeSettings;
 
-    timeRangeVisible = true;
+    @Output()
+    viewModeChange: EventEmitter<string> = new EventEmitter<string>();
+
+    @Output()
+    saveDashboardEmitter: EventEmitter<void> = new EventEmitter();
+
+    @Output()
+    discardDashboardEmitter: EventEmitter<void> = new EventEmitter();
+
+    @Output()
+    deleteDashboardEmitter: EventEmitter<void> = new EventEmitter();
 
     @Output()
-    saveDataViewEmitter: EventEmitter<void> = new EventEmitter();
+    triggerEditModeEmitter: EventEmitter<void> = new EventEmitter<void>();
 
     @Output()
     updateDateRangeEmitter: EventEmitter<TimeSettings> = new EventEmitter();
diff --git a/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/dashboard-widget-selection-panel.component.html b/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/dashboard-widget-selection-panel.component.html
new file mode 100644
index 0000000000..eea0f0d838
--- /dev/null
+++ b/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/dashboard-widget-selection-panel.component.html
@@ -0,0 +1,44 @@
+<!--
+  ~ 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" class="designer-panel-content" fxLayout="column">
+    <div fxLayout="row" class="sp-tab-bg designer-panel-header">
+        <div fxLayoutAlign="start center" class="designer-panel-title">
+            <span> Configure Dashboard </span>
+        </div>
+    </div>
+    <div fxFlex="100" fxLayout="column" class="no-overflow">
+        <mat-tab-group
+            color="accent"
+            fxFlexFill
+            class="small-tab-headers mat-tab-fill-height"
+        >
+            <mat-tab data-cy="designer-panel-data-config" label="Data Views">
+                <div class="scroll-tab-content">
+                    <sp-data-explorer-data-view-selection
+                        (addDataViewEmitter)="addDataViewEmitter.emit($event)"
+                    >
+                    </sp-data-explorer-data-view-selection>
+                </div>
+            </mat-tab>
+            <mat-tab data-cy="designer-panel-data-config" label="Layout">
+                <div class="scroll-tab-content">Layout</div>
+            </mat-tab>
+        </mat-tab-group>
+    </div>
+</div>
diff --git a/ui/src/app/data-explorer/components/designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.scss b/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/dashboard-widget-selection-panel.component.scss
similarity index 99%
copy from ui/src/app/data-explorer/components/designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.scss
copy to ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/dashboard-widget-selection-panel.component.scss
index 13cbc4aacb..e280dd74d5 100644
--- a/ui/src/app/data-explorer/components/designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.scss
+++ b/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/dashboard-widget-selection-panel.component.scss
@@ -1,4 +1,4 @@
-/*
+/*!
  * 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.
diff --git a/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.scss b/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/dashboard-widget-selection-panel.component.ts
similarity index 59%
copy from ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.scss
copy to ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/dashboard-widget-selection-panel.component.ts
index c1e524bb89..363a5a7e59 100644
--- a/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.scss
+++ b/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/dashboard-widget-selection-panel.component.ts
@@ -16,43 +16,17 @@
  *
  */
 
-.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);
-}
-
-.edit-menu-btn {
-    margin-right: 5px;
+import { Component, EventEmitter, Output } from '@angular/core';
+
+@Component({
+    selector: 'sp-data-explorer-dashboard-widget-selection-panel',
+    templateUrl: './dashboard-widget-selection-panel.component.html',
+    styleUrls: [
+        './dashboard-widget-selection-panel.component.scss',
+        '../../data-view/data-view-designer-panel/data-explorer-designer-panel.component.scss',
+    ],
+})
+export class DataExplorerDashboardWidgetSelectionPanelComponent {
+    @Output()
+    addDataViewEmitter: EventEmitter<string> = new EventEmitter<string>();
 }
diff --git a/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-preview/data-view-preview.component.html b/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-preview/data-view-preview.component.html
new file mode 100644
index 0000000000..dc77d00e81
--- /dev/null
+++ b/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-preview/data-view-preview.component.html
@@ -0,0 +1,52 @@
+<!--
+  ~ 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" class="data-view-preview-outer">
+    <div fxFlex fxLayout="column">
+        <h5>{{ dataView.baseAppearanceConfig.widgetTitle }}</h5>
+        <div fxLayout="row" fxLayoutGap="15px" class="data-view-preview-info">
+            <span fxLayoutAlign="start center"
+                ><i class="material-icons color-primary">insert_chart</i></span
+            >
+            <span fxFlex fxLayoutAlign="start center">{{
+                widgetTypeLabel
+            }}</span>
+        </div>
+        <div fxLayout="row" fxLayoutGap="15px" class="data-view-preview-info">
+            <span fxLayoutAlign="start center"
+                ><i class="material-icons">folder</i></span
+            >
+            <span fxFlex fxLayoutAlign="start center">{{
+                dataView.dataConfig.sourceConfigs[0].measureName
+            }}</span>
+        </div>
+    </div>
+    <div fxLayoutAlign="end center">
+        <button
+            mat-icon-button
+            color="accent"
+            [attr.data-cy]="
+                'add-data-view-btn-' +
+                dataView.baseAppearanceConfig.widgetTitle.replaceAll(' ', '')
+            "
+            (click)="addDataViewEmitter.emit(dataView.elementId)"
+        >
+            <i class="material-icons">add</i>
+        </button>
+    </div>
+</div>
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection-panel/field-selection-panel.component.scss b/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-preview/data-view-preview.component.scss
similarity index 76%
copy from ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection-panel/field-selection-panel.component.scss
copy to ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-preview/data-view-preview.component.scss
index 65a3b416cd..992ec84093 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection-panel/field-selection-panel.component.scss
+++ b/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-preview/data-view-preview.component.scss
@@ -1,4 +1,4 @@
-/*
+/*!
  * 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.
@@ -16,16 +16,16 @@
  *
  */
 
-.field-scroll-panel {
-    max-height: 100px;
-    overflow-y: auto;
-    overflow-x: hidden;
+.data-view-preview-outer {
+    border: 1px solid var(--color-bg-2);
+    padding: 10px;
 }
 
-.pull-btn-right {
-    margin-left: auto;
+.data-view-preview-outer:hover {
+    border-color: var(--color-bg-3);
+    background: var(--color-bg-1);
 }
 
-.btn-margin {
-    margin-right: 10px;
+.data-view-preview-info {
+    font-size: small;
 }
diff --git a/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-preview/data-view-preview.component.ts b/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-preview/data-view-preview.component.ts
new file mode 100644
index 0000000000..4734957e54
--- /dev/null
+++ b/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-preview/data-view-preview.component.ts
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { DataExplorerWidgetModel } from '@streampipes/platform-services';
+import { DataExplorerWidgetRegistry } from '../../../../../registry/data-explorer-widget-registry';
+
+@Component({
+    selector: 'sp-data-explorer-data-view-preview',
+    templateUrl: './data-view-preview.component.html',
+    styleUrls: ['./data-view-preview.component.scss'],
+})
+export class DataExplorerDataViewPreviewComponent implements OnInit {
+    @Input()
+    dataView: DataExplorerWidgetModel;
+
+    widgetTypeLabel: string;
+
+    @Output()
+    addDataViewEmitter: EventEmitter<string> = new EventEmitter<string>();
+
+    constructor(private widgetRegistryService: DataExplorerWidgetRegistry) {}
+
+    ngOnInit() {
+        this.widgetTypeLabel = this.widgetRegistryService.getWidgetTemplate(
+            this.dataView.widgetType,
+        ).label;
+    }
+}
diff --git a/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-selection.component.html b/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-selection.component.html
new file mode 100644
index 0000000000..3fb1c3cccc
--- /dev/null
+++ b/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-selection.component.html
@@ -0,0 +1,27 @@
+<!--
+  ~ 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" class="m-10" fxLayoutGap="10px" fxLayout="column">
+    <div *ngFor="let dataView of dataViews">
+        <sp-data-explorer-data-view-preview
+            [dataView]="dataView"
+            (addDataViewEmitter)="addDataViewEmitter.emit($event)"
+        >
+        </sp-data-explorer-data-view-preview>
+    </div>
+</div>
diff --git a/ui/src/app/data-explorer/components/designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.scss b/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-selection.component.scss
similarity index 96%
copy from ui/src/app/data-explorer/components/designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.scss
copy to ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-selection.component.scss
index 13cbc4aacb..198edb0cf3 100644
--- a/ui/src/app/data-explorer/components/designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.scss
+++ b/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-selection.component.scss
@@ -1,4 +1,4 @@
-/*
+/*!
  * 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.
@@ -15,3 +15,7 @@
  * limitations under the License.
  *
  */
+
+.m-10 {
+    margin: 10px;
+}
diff --git a/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-selection.component.ts b/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-selection.component.ts
new file mode 100644
index 0000000000..e3cb045741
--- /dev/null
+++ b/ui/src/app/data-explorer/components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-selection.component.ts
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, EventEmitter, OnInit, Output } from '@angular/core';
+import {
+    DataExplorerWidgetModel,
+    DataViewDataExplorerService,
+} from '@streampipes/platform-services';
+
+@Component({
+    selector: 'sp-data-explorer-data-view-selection',
+    templateUrl: './data-view-selection.component.html',
+    styleUrls: ['./data-view-selection.component.scss'],
+})
+export class DataExplorerDataViewSelectionComponent implements OnInit {
+    @Output()
+    addDataViewEmitter: EventEmitter<string> = new EventEmitter();
+
+    dataViews: DataExplorerWidgetModel[] = [];
+
+    constructor(private dataViewService: DataViewDataExplorerService) {}
+
+    ngOnInit() {
+        this.dataViewService.getAllWidgets().subscribe(dataViews => {
+            this.dataViews = dataViews.sort((a, b) =>
+                a.baseAppearanceConfig.widgetTitle.localeCompare(
+                    b.baseAppearanceConfig.widgetTitle,
+                ),
+            );
+        });
+    }
+}
diff --git a/ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.html b/ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.html
new file mode 100644
index 0000000000..f5e4d0e2be
--- /dev/null
+++ b/ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.html
@@ -0,0 +1,105 @@
+<!--
+  ~ 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="dashboardLoaded"
+>
+    <div nav fxFlex="100" class="ml-10">
+        <sp-data-explorer-dashboard-toolbar
+            [editMode]="editMode"
+            [(viewMode)]="viewMode"
+            [hasDataExplorerDeletePrivileges]="hasDataExplorerDeletePrivileges"
+            [hasDataExplorerWritePrivileges]="hasDataExplorerWritePrivileges"
+            [timeRangeVisible]="timeRangeVisible"
+            [timeSettings]="timeSettings"
+            (saveDashboardEmitter)="persistDashboardChanges()"
+            (discardDashboardEmitter)="discardChanges()"
+            (deleteDashboardEmitter)="deleteDashboard()"
+            (triggerEditModeEmitter)="triggerEditMode()"
+            (updateDateRangeEmitter)="updateDateRange($event)"
+        >
+        </sp-data-explorer-dashboard-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-dashboard-widget-selection-panel
+                        (addDataViewEmitter)="addDataViewToDashboard($event)"
+                        fxFlex="100"
+                    >
+                    </sp-data-explorer-dashboard-widget-selection-panel>
+                </div>
+            </mat-drawer>
+            <mat-drawer-content class="h-100 dashboard-grid">
+                <div
+                    *ngIf="showEditingHelpInfo"
+                    fxFlex="100"
+                    fxLayout="column"
+                    fxLayoutAlign="center center"
+                >
+                    <h4>
+                        This data view is empty and doesn't contain any widgets.
+                    </h4>
+                    <button
+                        mat-button
+                        mat-raised-button
+                        color="accent"
+                        *ngIf="hasDataExplorerWritePrivileges"
+                        (click)="triggerEditMode()"
+                    >
+                        <mat-icon>add</mat-icon>
+                        Add widget
+                    </button>
+                </div>
+                <sp-data-explorer-dashboard-grid
+                    #dashboardGrid
+                    *ngIf="!showEditingHelpInfo && viewMode === 'grid'"
+                    [editMode]="editMode"
+                    [dashboard]="dashboard"
+                    [timeSettings]="timeSettings"
+                    (deleteCallback)="removeDataViewFromDashboard($event)"
+                    (startEditModeEmitter)="startEditMode($event)"
+                    class="h-100 dashboard-grid"
+                >
+                </sp-data-explorer-dashboard-grid>
+                <sp-data-explorer-dashboard-slide-view
+                    class="h-100 dashboard-grid"
+                    #dashboardSlide
+                    [editMode]="editMode"
+                    [dashboard]="dashboard"
+                    [timeSettings]="timeSettings"
+                    (deleteCallback)="removeDataViewFromDashboard($event)"
+                    (startEditModeEmitter)="startEditMode($event)"
+                    *ngIf="!showEditingHelpInfo && viewMode === 'slide'"
+                >
+                </sp-data-explorer-dashboard-slide-view>
+            </mat-drawer-content>
+        </mat-drawer-container>
+    </div>
+</sp-basic-view>
diff --git a/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.scss b/ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.scss
similarity index 90%
rename from ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.scss
rename to ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.scss
index c1e524bb89..285b384708 100644
--- a/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.scss
+++ b/ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.scss
@@ -1,4 +1,4 @@
-/*
+/*!
  * 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.
@@ -20,15 +20,6 @@
     height: 50px;
 }
 
-.data-explorer-options {
-    padding: 0px;
-}
-
-.data-explorer-options-item {
-    display: inline;
-    margin-right: 10px;
-}
-
 .m-20 {
     margin: 20px;
 }
diff --git a/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.ts b/ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.ts
similarity index 55%
rename from ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.ts
rename to ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.ts
index 5b33a4bfc1..d29b19a2bd 100644
--- a/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.ts
+++ b/ui/src/app/data-explorer/components/dashboard/data-explorer-dashboard-panel.component.ts
@@ -17,10 +17,8 @@
  */
 
 import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
-import { Observable, of, Subscription, zip } from 'rxjs';
+import { Observable, of, Subscription } from 'rxjs';
 import { DataExplorerDashboardGridComponent } from '../widget-view/grid-view/data-explorer-dashboard-grid.component';
-import { MatDrawer } from '@angular/material/sidenav';
-import { Tuple2 } from '../../../core-model/base/Tuple2';
 import {
     ClientDashboardItem,
     Dashboard,
@@ -29,14 +27,12 @@ import {
     DataViewDataExplorerService,
     TimeSettings,
 } from '@streampipes/platform-services';
-import { DataExplorerDesignerPanelComponent } from '../designer-panel/data-explorer-designer-panel.component';
 import { TimeSelectionService } from '../../services/time-selection.service';
 import { AuthService } from '../../../services/auth.service';
 import { UserPrivilege } from '../../../_enums/user-privilege.enum';
 import {
     ActivatedRoute,
     ActivatedRouteSnapshot,
-    Router,
     RouterStateSnapshot,
 } from '@angular/router';
 import { DataExplorerDashboardSlideViewComponent } from '../widget-view/slide-view/data-explorer-dashboard-slide-view.component';
@@ -48,6 +44,7 @@ import {
 import { MatDialog } from '@angular/material/dialog';
 import { map } from 'rxjs/operators';
 import { SpDataExplorerRoutes } from '../../data-explorer.routes';
+import { DataExplorerRoutingService } from '../../services/data-explorer-routing.service';
 
 @Component({
     selector: 'sp-data-explorer-dashboard-panel',
@@ -73,31 +70,13 @@ export class DataExplorerDashboardPanelComponent implements OnInit, OnDestroy {
     @ViewChild('dashboardSlide')
     dashboardSlide: DataExplorerDashboardSlideViewComponent;
 
-    @ViewChild('designerDrawer')
-    designerDrawer: MatDrawer;
-
-    @ViewChild('designerPanel')
-    designerPanel: DataExplorerDesignerPanelComponent;
-
     hasDataExplorerWritePrivileges = false;
     hasDataExplorerDeletePrivileges = false;
 
     public items: Dashboard[];
 
-    widgetIdsToRemove: string[] = [];
-    widgetsToUpdate: Map<string, DataExplorerWidgetModel> = new Map<
-        string,
-        DataExplorerWidgetModel
-    >();
-
-    currentlyConfiguredWidget: DataExplorerWidgetModel;
-    newWidgetMode = false;
-    currentlyConfiguredWidgetId: string;
     dataLakeMeasure: DataLakeMeasure;
-
-    showDesignerPanel = false;
     showEditingHelpInfo = false;
-
     authSubscription: Subscription;
 
     constructor(
@@ -109,7 +88,7 @@ export class DataExplorerDashboardPanelComponent implements OnInit, OnDestroy {
         private dashboardService: DataViewDataExplorerService,
         private route: ActivatedRoute,
         private dataViewService: DataViewDataExplorerService,
-        private router: Router,
+        private routingService: DataExplorerRoutingService,
         private breadcrumbService: SpBreadcrumbService,
     ) {}
 
@@ -129,49 +108,29 @@ export class DataExplorerDashboardPanelComponent implements OnInit, OnDestroy {
             this.hasDataExplorerDeletePrivileges = this.authService.hasRole(
                 UserPrivilege.PRIVILEGE_DELETE_DATA_EXPLORER_VIEW,
             );
-            if (
-                queryParams.action === 'edit' &&
-                this.hasDataExplorerWritePrivileges
-            ) {
+            if (queryParams.editMode && this.hasDataExplorerWritePrivileges) {
                 this.editMode = true;
             }
         });
     }
 
     ngOnDestroy() {
-        if (this.authSubscription) {
-            this.authSubscription.unsubscribe();
-        }
+        this.authSubscription?.unsubscribe();
     }
 
-    triggerResize() {
-        window.dispatchEvent(new Event('resize'));
-    }
-
-    addWidget(
-        widgetConfig: Tuple2<DataLakeMeasure, DataExplorerWidgetModel>,
-    ): void {
-        this.dataLakeMeasure = widgetConfig.a;
-        this.dataViewDataExplorerService
-            .saveWidget(widgetConfig.b)
-            .subscribe(response => {
-                this.addWidgetToDashboard(response);
-            });
-    }
-
-    addWidgetToDashboard(widget: DataExplorerWidgetModel) {
+    addDataViewToDashboard(dataViewElementId: string) {
         // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
         const dashboardItem = {} as ClientDashboardItem;
-        dashboardItem.id = widget.elementId;
+        dashboardItem.id = dataViewElementId;
         dashboardItem.cols = 3;
         dashboardItem.rows = 4;
         dashboardItem.x = 0;
         dashboardItem.y = 0;
         this.dashboard.widgets.push(dashboardItem);
         if (this.viewMode === 'grid') {
-            this.dashboardGrid.loadWidgetConfig(widget.elementId, true);
+            this.dashboardGrid.loadWidgetConfig(dataViewElementId, true);
         } else {
-            this.dashboardSlide.loadWidgetConfig(widget.elementId, true);
+            this.dashboardSlide.loadWidgetConfig(dataViewElementId, true);
         }
     }
 
@@ -179,64 +138,23 @@ export class DataExplorerDashboardPanelComponent implements OnInit, OnDestroy {
         this.dataViewDataExplorerService
             .updateDashboard(this.dashboard)
             .subscribe(result => {
-                this.dashboard.rev = result.rev;
-                if (this.widgetIdsToRemove.length > 0) {
-                    const observables = this.deleteWidgets();
-                    zip(...observables).subscribe(() => {
-                        this.widgetIdsToRemove.forEach(id => {
-                            if (this.viewMode === 'grid') {
-                                this.dashboardGrid.configuredWidgets.delete(id);
-                            } else {
-                                this.dashboardSlide.configuredWidgets.delete(
-                                    id,
-                                );
-                            }
-                        });
-
-                        this.afterDashboardChange();
-                    });
-                } else {
-                    this.afterDashboardChange();
-                }
+                this.routingService.navigateToOverview(true);
             });
-
-        this.editMode = false;
-    }
-
-    afterDashboardChange() {
-        if (this.viewMode === 'grid') {
-            this.dashboardGrid.updateAllWidgets();
-        } else {
-            this.dashboardSlide.updateAllWidgets();
-        }
-        this.closeDesignerPanel();
     }
 
     startEditMode(widgetModel: DataExplorerWidgetModel) {
-        this.editMode = true;
-        this.updateCurrentlyConfiguredWidget(widgetModel);
-        this.showEditingHelpInfo = false;
+        this.routingService.navigateToDataView(
+            true,
+            widgetModel.elementId,
+            true,
+        );
     }
 
-    removeAndQueueItemForDeletion(widget: DataExplorerWidgetModel) {
+    removeDataViewFromDashboard(widget: DataExplorerWidgetModel) {
         const index = this.dashboard.widgets.findIndex(
             item => item.id === widget.elementId,
         );
         this.dashboard.widgets.splice(index, 1);
-        this.widgetIdsToRemove.push(widget.elementId);
-        if (this.currentlyConfiguredWidget.elementId === widget.elementId) {
-            this.currentlyConfiguredWidget = undefined;
-        }
-    }
-
-    updateAndQueueItemForDeletion(widget: DataExplorerWidgetModel) {
-        this.widgetsToUpdate.set(widget.elementId, widget);
-    }
-
-    deleteWidgets(): Observable<any>[] {
-        return this.widgetIdsToRemove.map(widgetId => {
-            return this.dataViewDataExplorerService.deleteWidget(widgetId);
-        });
     }
 
     updateDateRange(timeSettings: TimeSettings) {
@@ -245,70 +163,17 @@ export class DataExplorerDashboardPanelComponent implements OnInit, OnDestroy {
         this.timeSelectionService.notify(timeSettings);
     }
 
-    updateCurrentlyConfiguredWidget(currentWidget: DataExplorerWidgetModel) {
-        if (currentWidget) {
-            this.widgetsToUpdate.set(currentWidget.elementId, currentWidget);
-            this.currentlyConfiguredWidget = currentWidget;
-            this.currentlyConfiguredWidgetId = currentWidget.elementId;
-            this.designerPanel.modifyWidgetMode(currentWidget, false);
-            this.showDesignerPanel = true;
-        } else {
-            this.showDesignerPanel = false;
-        }
-    }
-
     discardChanges() {
         this.editMode = false;
     }
 
     triggerEditMode() {
         this.showEditingHelpInfo = false;
-        if (this.dashboard.widgets.length > 0) {
-            this.currentlyConfiguredWidgetId = this.dashboard.widgets[0].id;
-            const currentView = this.dashboardGrid
-                ? this.dashboardGrid
-                : this.dashboardSlide;
-            currentView.selectFirstWidgetForEditing(
-                this.currentlyConfiguredWidgetId,
-            );
-        } else {
-            this.editMode = true;
-            this.createWidget();
-        }
-    }
-
-    createWidget() {
-        this.dataLakeMeasure = new DataLakeMeasure();
-        this.currentlyConfiguredWidget = new DataExplorerWidgetModel();
-        this.currentlyConfiguredWidget['@class'] =
-            'org.apache.streampipes.model.datalake.DataExplorerWidgetModel';
-        this.currentlyConfiguredWidget.baseAppearanceConfig = {};
-        this.currentlyConfiguredWidget.baseAppearanceConfig.widgetTitle =
-            'New Widget';
-        this.currentlyConfiguredWidget.dataConfig = {};
-        this.currentlyConfiguredWidget.dataConfig.ignoreMissingValues = false;
-        this.currentlyConfiguredWidget.baseAppearanceConfig.backgroundColor =
-            '#FFFFFF';
-        this.currentlyConfiguredWidget.baseAppearanceConfig.textColor =
-            '#3e3e3e';
-        this.currentlyConfiguredWidget = { ...this.currentlyConfiguredWidget };
-        this.newWidgetMode = true;
-        this.showDesignerPanel = true;
-        this.newWidgetMode = true;
-        if (this.designerPanel) {
-            this.designerPanel.resetIndex();
-        }
-    }
-
-    closeDesignerPanel() {
-        this.showDesignerPanel = false;
-        this.currentlyConfiguredWidget = undefined;
-        this.dataLakeMeasure = undefined;
-        this.currentlyConfiguredWidgetId = undefined;
+        this.editMode = true;
     }
 
-    deleteDashboard(dashboard: Dashboard) {
-        this.dashboardService.deleteDashboard(dashboard).subscribe(_ => {
+    deleteDashboard() {
+        this.dashboardService.deleteDashboard(this.dashboard).subscribe(_ => {
             this.goBackToOverview();
         });
     }
@@ -345,12 +210,12 @@ export class DataExplorerDashboardPanelComponent implements OnInit, OnDestroy {
     }
 
     goBackToOverview() {
-        this.router.navigate(['dataexplorer']);
+        this.routingService.navigateToOverview();
     }
 
     confirmLeaveDashboard(
-        route: ActivatedRouteSnapshot,
-        state: RouterStateSnapshot,
+        _route: ActivatedRouteSnapshot,
+        _state: RouterStateSnapshot,
     ): Observable<boolean> {
         if (this.editMode) {
             const dialogRef = this.dialog.open(ConfirmDialogComponent, {
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
index 4cd25092a3..5ddeee5a14 100644
--- 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
@@ -30,6 +30,7 @@
     >
         <sp-data-explorer-data-view-toolbar
             [timeSettings]="timeSettings"
+            (downloadFileEmitter)="downloadDataAsFile()"
             (updateDateRangeEmitter)="updateDateRange($event)"
             (saveDataViewEmitter)="saveDataView()"
             fxFlex="100"
@@ -59,12 +60,14 @@
                 <div #panel fxFlex="100" fxLayout="column">
                     <sp-data-explorer-dashboard-widget
                         *ngIf="dataView && gridsterItemComponent"
+                        [dataViewMode]="true"
                         [configuredWidget]="dataView"
                         [gridsterItemComponent]="gridsterItemComponent"
                         [timeSettings]="timeSettings"
                         [dataLakeMeasure]="
                             dataView.dataConfig.sourceConfigs[0].measure
                         "
+                        (startEditModeEmitter)="editDataView()"
                     >
                     </sp-data-explorer-dashboard-widget>
                 </div>
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
index 478328c207..e7c6225ff4 100644
--- 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
@@ -23,8 +23,11 @@ import {
     DataViewDataExplorerService,
     TimeSettings,
 } from '@streampipes/platform-services';
-import { ActivatedRoute, Router } from '@angular/router';
+import { ActivatedRoute } from '@angular/router';
 import { TimeSelectionService } from '../../services/time-selection.service';
+import { DataExplorerRoutingService } from '../../services/data-explorer-routing.service';
+import { DialogService } from '@streampipes/shared-ui';
+import { DataExplorerDashboardService } from '../../services/data-explorer-dashboard.service';
 
 @Component({
     selector: 'sp-data-explorer-data-view',
@@ -43,8 +46,10 @@ export class DataExplorerDataViewComponent implements OnInit {
     @ViewChild('panel', { static: false }) outerPanel: ElementRef;
 
     constructor(
+        private dialogService: DialogService,
+        private dashboardService: DataExplorerDashboardService,
         private route: ActivatedRoute,
-        private router: Router,
+        private routingService: DataExplorerRoutingService,
         private dataViewService: DataViewDataExplorerService,
         private timeSelectionService: TimeSelectionService,
     ) {}
@@ -54,16 +59,7 @@ export class DataExplorerDataViewComponent implements OnInit {
         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();
-            });
+            this.loadDataView(dataViewId);
         } else {
             this.createWidget();
             this.timeSettings = this.makeDefaultTimeSettings();
@@ -71,6 +67,19 @@ export class DataExplorerDataViewComponent implements OnInit {
         }
     }
 
+    loadDataView(dataViewId: string): void {
+        this.dataViewLoaded = false;
+        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();
+        });
+    }
+
     afterDataViewLoaded(): void {
         this.dataViewLoaded = true;
         setTimeout(() => {
@@ -81,6 +90,10 @@ export class DataExplorerDataViewComponent implements OnInit {
         });
     }
 
+    editDataView(): void {
+        this.routingService.navigateToDataView(true, this.dataView.elementId);
+    }
+
     makeDefaultTimeSettings(): TimeSettings {
         return {
             dynamicSelection: 1440,
@@ -105,11 +118,12 @@ export class DataExplorerDataViewComponent implements OnInit {
 
     saveDataView(): void {
         this.dataView.timeSettings = this.timeSettings;
-        const observable = this.editMode
-            ? this.dataViewService.updateWidget(this.dataView)
-            : this.dataViewService.saveWidget(this.dataView);
+        const observable =
+            this.dataView.elementId !== undefined
+                ? this.dataViewService.updateWidget(this.dataView)
+                : this.dataViewService.saveWidget(this.dataView);
         observable.subscribe(() => {
-            this.router.navigate(['dataexplorer']);
+            this.routingService.navigateToOverview();
         });
     }
 
@@ -117,4 +131,11 @@ export class DataExplorerDataViewComponent implements OnInit {
         this.timeSettings = timeSettings;
         this.timeSelectionService.notify(timeSettings);
     }
+
+    downloadDataAsFile() {
+        this.dashboardService.downloadDataAsFile(
+            this.timeSettings,
+            this.dataView,
+        );
+    }
 }
diff --git a/ui/src/app/data-explorer/components/designer-panel/appearance-settings/data-explorer-widget-appearance-settings.component.html b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/appearance-settings/data-explorer-widget-appearance-settings.component.html
similarity index 98%
rename from ui/src/app/data-explorer/components/designer-panel/appearance-settings/data-explorer-widget-appearance-settings.component.html
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/appearance-settings/data-explorer-widget-appearance-settings.component.html
index d987bbe97b..0fd30a0d78 100644
--- a/ui/src/app/data-explorer/components/designer-panel/appearance-settings/data-explorer-widget-appearance-settings.component.html
+++ b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/appearance-settings/data-explorer-widget-appearance-settings.component.html
@@ -20,6 +20,7 @@
     <div fxFlex="100" fxLayout="row" class="mt-10 form-field-small">
         <mat-form-field appearance="outline" color="accent" fxFlex="100">
             <input
+                data-cy="appearance-config-widget-title"
                 matInput
                 [(ngModel)]="
                     currentlyConfiguredWidget.baseAppearanceConfig.widgetTitle
diff --git a/ui/src/app/data-explorer/components/designer-panel/appearance-settings/data-explorer-widget-appearance-settings.component.scss b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/appearance-settings/data-explorer-widget-appearance-settings.component.scss
similarity index 100%
rename from ui/src/app/data-explorer/components/designer-panel/appearance-settings/data-explorer-widget-appearance-settings.component.scss
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/appearance-settings/data-explorer-widget-appearance-settings.component.scss
diff --git a/ui/src/app/data-explorer/components/designer-panel/appearance-settings/data-explorer-widget-appearance-settings.component.ts b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/appearance-settings/data-explorer-widget-appearance-settings.component.ts
similarity index 92%
rename from ui/src/app/data-explorer/components/designer-panel/appearance-settings/data-explorer-widget-appearance-settings.component.ts
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/appearance-settings/data-explorer-widget-appearance-settings.component.ts
index 9c6adcaaa8..d077141cf7 100644
--- a/ui/src/app/data-explorer/components/designer-panel/appearance-settings/data-explorer-widget-appearance-settings.component.ts
+++ b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/appearance-settings/data-explorer-widget-appearance-settings.component.ts
@@ -17,10 +17,10 @@
  */
 
 import { Component, Input, OnDestroy, OnInit } from '@angular/core';
-import { WidgetConfigurationService } from '../../../services/widget-configuration.service';
+import { WidgetConfigurationService } from '../../../../services/widget-configuration.service';
 import { DataExplorerWidgetModel } from '@streampipes/platform-services';
-import { WidgetTypeService } from '../../../services/widget-type.service';
-import { DataExplorerWidgetRegistry } from '../../../registry/data-explorer-widget-registry';
+import { WidgetTypeService } from '../../../../services/widget-type.service';
+import { DataExplorerWidgetRegistry } from '../../../../registry/data-explorer-widget-registry';
 import { Subscription } from 'rxjs';
 
 @Component({
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.html b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-explorer-designer-panel.component.html
similarity index 100%
rename from ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.html
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-explorer-designer-panel.component.html
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.scss b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-explorer-designer-panel.component.scss
similarity index 95%
rename from ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.scss
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-explorer-designer-panel.component.scss
index a473489e0e..89b6abd1ba 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.scss
+++ b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-explorer-designer-panel.component.scss
@@ -16,7 +16,7 @@
  *
  */
 
-@import '../../../../scss/sp/sp-dialog.scss';
+@import '../../../../../scss/sp/sp-dialog.scss';
 
 .designer-panel-content {
     padding: 0;
@@ -33,6 +33,7 @@
     margin-left: 20px;
     font-size: 12pt;
     font-weight: bold;
+    height: 40px;
 }
 
 .designer-panel-header {
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.ts b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-explorer-designer-panel.component.ts
similarity index 98%
rename from ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.ts
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-explorer-designer-panel.component.ts
index 2b5eb57efc..f2400158ac 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.ts
+++ b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-explorer-designer-panel.component.ts
@@ -27,7 +27,7 @@ import {
     DataExplorerWidgetModel,
     DataLakeMeasure,
 } from '@streampipes/platform-services';
-import { Tuple2 } from '../../../core-model/base/Tuple2';
+import { Tuple2 } from '../../../../core-model/base/Tuple2';
 import { DataExplorerWidgetDataSettingsComponent } from './data-settings/data-explorer-widget-data-settings.component';
 
 @Component({
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.html b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/data-explorer-widget-data-settings.component.html
similarity index 100%
rename from ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.html
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/data-explorer-widget-data-settings.component.html
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.scss b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/data-explorer-widget-data-settings.component.scss
similarity index 100%
rename from ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.scss
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/data-explorer-widget-data-settings.component.scss
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.ts b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/data-explorer-widget-data-settings.component.ts
similarity index 98%
rename from ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.ts
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/data-explorer-widget-data-settings.component.ts
index 38eb68730f..f780e87b06 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-settings/data-explorer-widget-data-settings.component.ts
+++ b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/data-explorer-widget-data-settings.component.ts
@@ -32,9 +32,9 @@ import {
     DataViewDataExplorerService,
     SourceConfig,
 } from '@streampipes/platform-services';
-import { Tuple2 } from '../../../../core-model/base/Tuple2';
+import { Tuple2 } from '../../../../../core-model/base/Tuple2';
 import { zip } from 'rxjs';
-import { WidgetConfigurationService } from '../../../services/widget-configuration.service';
+import { WidgetConfigurationService } from '../../../../services/widget-configuration.service';
 import { FieldSelectionPanelComponent } from './field-selection-panel/field-selection-panel.component';
 import { GroupSelectionPanelComponent } from './group-selection-panel/group-selection-panel.component';
 
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection-panel/field-selection-panel.component.html b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/field-selection-panel/field-selection-panel.component.html
similarity index 100%
rename from ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection-panel/field-selection-panel.component.html
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/field-selection-panel/field-selection-panel.component.html
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection-panel/field-selection-panel.component.scss b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/field-selection-panel/field-selection-panel.component.scss
similarity index 100%
rename from ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection-panel/field-selection-panel.component.scss
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/field-selection-panel/field-selection-panel.component.scss
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection-panel/field-selection-panel.component.ts b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/field-selection-panel/field-selection-panel.component.ts
similarity index 95%
rename from ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection-panel/field-selection-panel.component.ts
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/field-selection-panel/field-selection-panel.component.ts
index d9d892b947..6da1c34cd2 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection-panel/field-selection-panel.component.ts
+++ b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/field-selection-panel/field-selection-panel.component.ts
@@ -22,8 +22,8 @@ import {
     FieldConfig,
     SourceConfig,
 } from '@streampipes/platform-services';
-import { DataExplorerFieldProviderService } from '../../../../services/data-explorer-field-provider-service';
-import { WidgetConfigurationService } from '../../../../services/widget-configuration.service';
+import { DataExplorerFieldProviderService } from '../../../../../services/data-explorer-field-provider-service';
+import { WidgetConfigurationService } from '../../../../../services/widget-configuration.service';
 
 @Component({
     selector: 'sp-field-selection-panel',
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection/field-selection.component.html b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/field-selection/field-selection.component.html
similarity index 100%
rename from ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection/field-selection.component.html
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/field-selection/field-selection.component.html
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection/field-selection.component.scss b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/field-selection/field-selection.component.scss
similarity index 100%
rename from ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection/field-selection.component.scss
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/field-selection/field-selection.component.scss
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection/field-selection.component.ts b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/field-selection/field-selection.component.ts
similarity index 94%
rename from ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection/field-selection.component.ts
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/field-selection/field-selection.component.ts
index e7db6f6f40..9c67c91b61 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-settings/field-selection/field-selection.component.ts
+++ b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/field-selection/field-selection.component.ts
@@ -22,7 +22,7 @@ import {
     FieldConfig,
     SourceConfig,
 } from '@streampipes/platform-services';
-import { WidgetConfigurationService } from '../../../../services/widget-configuration.service';
+import { WidgetConfigurationService } from '../../../../../services/widget-configuration.service';
 
 @Component({
     selector: 'sp-field-selection',
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.html b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.html
similarity index 100%
rename from ui/src/app/data-explorer/components/designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.html
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.html
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.scss b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.scss
similarity index 100%
rename from ui/src/app/data-explorer/components/designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.scss
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.scss
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.ts b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.ts
similarity index 95%
rename from ui/src/app/data-explorer/components/designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.ts
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.ts
index 03fe6fe2f3..ecdec5f465 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.ts
+++ b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component.ts
@@ -23,8 +23,8 @@ import {
     SelectedFilter,
     SourceConfig,
 } from '@streampipes/platform-services';
-import { WidgetConfigurationService } from '../../../../services/widget-configuration.service';
-import { DataExplorerFieldProviderService } from '../../../../services/data-explorer-field-provider-service';
+import { WidgetConfigurationService } from '../../../../../services/widget-configuration.service';
+import { DataExplorerFieldProviderService } from '../../../../../services/data-explorer-field-provider-service';
 
 @Component({
     selector: 'sp-filter-selection-panel',
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/group-selection-panel/group-selection-panel.component.html b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/group-selection-panel/group-selection-panel.component.html
similarity index 100%
rename from ui/src/app/data-explorer/components/designer-panel/data-settings/group-selection-panel/group-selection-panel.component.html
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/group-selection-panel/group-selection-panel.component.html
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/group-selection-panel/group-selection-panel.component.scss b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/group-selection-panel/group-selection-panel.component.scss
similarity index 100%
rename from ui/src/app/data-explorer/components/designer-panel/data-settings/group-selection-panel/group-selection-panel.component.scss
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/group-selection-panel/group-selection-panel.component.scss
diff --git a/ui/src/app/data-explorer/components/designer-panel/data-settings/group-selection-panel/group-selection-panel.component.ts b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/group-selection-panel/group-selection-panel.component.ts
similarity index 93%
rename from ui/src/app/data-explorer/components/designer-panel/data-settings/group-selection-panel/group-selection-panel.component.ts
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/group-selection-panel/group-selection-panel.component.ts
index 80c20febdc..a6e05965df 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-settings/group-selection-panel/group-selection-panel.component.ts
+++ b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/data-settings/group-selection-panel/group-selection-panel.component.ts
@@ -17,8 +17,8 @@
  */
 
 import { Component, Input, OnInit } from '@angular/core';
-import { DataExplorerFieldProviderService } from '../../../../services/data-explorer-field-provider-service';
-import { WidgetConfigurationService } from '../../../../services/widget-configuration.service';
+import { DataExplorerFieldProviderService } from '../../../../../services/data-explorer-field-provider-service';
+import { WidgetConfigurationService } from '../../../../../services/widget-configuration.service';
 import {
     EventPropertyUnion,
     FieldConfig,
diff --git a/ui/src/app/data-explorer/components/designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.html b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.html
similarity index 100%
rename from ui/src/app/data-explorer/components/designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.html
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.html
diff --git a/ui/src/app/data-explorer/components/designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.scss b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.scss
similarity index 100%
rename from ui/src/app/data-explorer/components/designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.scss
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.scss
diff --git a/ui/src/app/data-explorer/components/designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.ts b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.ts
similarity index 90%
rename from ui/src/app/data-explorer/components/designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.ts
rename to ui/src/app/data-explorer/components/data-view/data-view-designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.ts
index 8b8b3b8899..cc5bd31b0b 100644
--- a/ui/src/app/data-explorer/components/designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.ts
+++ b/ui/src/app/data-explorer/components/data-view/data-view-designer-panel/visualisation-settings/data-explorer-visualisation-settings.component.ts
@@ -24,10 +24,10 @@ import {
     SimpleChanges,
 } from '@angular/core';
 import { DataExplorerWidgetModel } from '@streampipes/platform-services';
-import { WidgetTypeService } from '../../../services/widget-type.service';
+import { WidgetTypeService } from '../../../../services/widget-type.service';
 import { MatSelectChange } from '@angular/material/select';
-import { IWidget } from '../../../models/dataview-dashboard.model';
-import { DataExplorerWidgetRegistry } from '../../../registry/data-explorer-widget-registry';
+import { IWidget } from '../../../../models/dataview-dashboard.model';
+import { DataExplorerWidgetRegistry } from '../../../../registry/data-explorer-widget-registry';
 
 @Component({
     selector: 'sp-explorer-visualisation-settings',
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
index 4be9360243..04ae11e225 100644
--- 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
@@ -30,10 +30,29 @@
             matTooltip="Save"
             class="edit-menu-btn"
             (click)="saveDataViewEmitter.emit()"
-            data-cy="save-data-explorer-widget-btn"
+            data-cy="save-data-view-btn"
         >
             <mat-icon>save</mat-icon>
-            Save data view
+            Save
+        </button>
+        <button
+            mat-raised-button
+            matTooltip="Discard"
+            class="mat-basic mr-10 edit-menu-btn"
+            (click)="discardDataViewEmitter.emit()"
+            data-cy="discard-data-explorer-widget-btn"
+        >
+            <i class="material-icons">undo</i>
+            <span>&nbsp;Discard</span>
+        </button>
+        <button
+            mat-icon-button
+            color="accent"
+            matTooltip="Download data"
+            (click)="downloadFileEmitter.emit()"
+            data-cy="data-view-data-download-btn"
+        >
+            <mat-icon>get_app</mat-icon>
         </button>
         <span fxFlex></span>
         <div
diff --git a/ui/src/app/data-explorer/components/data-view/data-view-toolbar/data-explorer-data-view-toolbar.component.ts b/ui/src/app/data-explorer/components/data-view/data-view-toolbar/data-explorer-data-view-toolbar.component.ts
index 37295d4769..167db1895f 100644
--- a/ui/src/app/data-explorer/components/data-view/data-view-toolbar/data-explorer-data-view-toolbar.component.ts
+++ b/ui/src/app/data-explorer/components/data-view/data-view-toolbar/data-explorer-data-view-toolbar.component.ts
@@ -35,6 +35,12 @@ export class DataExplorerDataViewToolbarComponent {
     @Output()
     saveDataViewEmitter: EventEmitter<void> = new EventEmitter();
 
+    @Output()
+    discardDataViewEmitter: EventEmitter<void> = new EventEmitter();
+
     @Output()
     updateDateRangeEmitter: EventEmitter<TimeSettings> = new EventEmitter();
+
+    @Output()
+    downloadFileEmitter: EventEmitter<void> = new EventEmitter();
 }
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
index a2eae808fa..4ada6cdaed 100644
--- 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
@@ -33,7 +33,7 @@
                     mat-header-cell
                     *matHeaderCellDef
                 >
-                    Data View
+                    Dashboard
                 </th>
                 <td
                     fxFlex="60"
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
index a883f94f62..1ccaeb0f4d 100644
--- 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
@@ -29,9 +29,9 @@ import {
     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';
+import { DataExplorerRoutingService } from '../../../services/data-explorer-routing.service';
 
 @Component({
     selector: 'sp-data-explorer-dashboard-overview',
@@ -48,11 +48,11 @@ export class SpDataExplorerDashboardOverviewComponent extends SpDataExplorerOver
         private dashboardService: DataViewDataExplorerService,
         private dataExplorerDashboardService: DataExplorerDashboardService,
         public dialogService: DialogService,
-        router: Router,
+        routingService: DataExplorerRoutingService,
         authService: AuthService,
         currentUserService: CurrentUserService,
     ) {
-        super(dialogService, authService, currentUserService, router);
+        super(dialogService, authService, currentUserService, routingService);
     }
 
     afterInit(): void {
@@ -101,20 +101,11 @@ export class SpDataExplorerDashboardOverviewComponent extends SpDataExplorerOver
     }
 
     showDashboard(dashboard: Dashboard) {
-        this.router.navigate([
-            'dataexplorer',
-            'dashboard',
-            dashboard.elementId,
-        ]);
+        this.routingService.navigateToDashboard(false, dashboard.elementId);
     }
 
     editDashboard(dashboard: Dashboard) {
-        this.router.navigate(
-            ['dataexplorer', 'dashboard', dashboard.elementId],
-            {
-                queryParams: { action: 'edit' },
-            },
-        );
+        this.routingService.navigateToDashboard(true, dashboard.elementId);
     }
 
     getDashboards() {
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
index 7d09daa464..e175e52353 100644
--- 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
@@ -72,7 +72,13 @@
                             color="accent"
                             matTooltip="Edit data view"
                             *ngIf="hasDataExplorerWritePrivileges"
-                            [attr.data-cy]="'edit-data-view-' + element.name"
+                            [attr.data-cy]="
+                                'edit-data-view-' +
+                                element.baseAppearanceConfig.widgetTitle.replaceAll(
+                                    ' ',
+                                    ''
+                                )
+                            "
                             (click)="openDataView(element, true)"
                         >
                             <i class="material-icons">edit</i>
@@ -82,7 +88,10 @@
                             color="accent"
                             matTooltip="Delete data view"
                             *ngIf="hasDataExplorerDeletePrivileges"
-                            [attr.data-cy]="'delete-data-view-' + element.name"
+                            [attr.data-cy]="
+                                'delete-data-view-' +
+                                element.baseAppearanceConfig.widgetTitle
+                            "
                             (click)="deleteDataView(element)"
                         >
                             <i class="material-icons">delete</i>
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
index 277ef2b5cf..aa1fea2166 100644
--- 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
@@ -25,8 +25,8 @@ import {
     DataViewDataExplorerService,
 } from '@streampipes/platform-services';
 import { CurrentUserService, DialogService } from '@streampipes/shared-ui';
-import { Router } from '@angular/router';
 import { AuthService } from '../../../../services/auth.service';
+import { DataExplorerRoutingService } from '../../../services/data-explorer-routing.service';
 
 @Component({
     selector: 'sp-data-explorer-data-view-overview',
@@ -43,9 +43,9 @@ export class SpDataExplorerDataViewOverviewComponent extends SpDataExplorerOverv
         public dialogService: DialogService,
         authService: AuthService,
         currentUserService: CurrentUserService,
-        router: Router,
+        routingService: DataExplorerRoutingService,
     ) {
-        super(dialogService, authService, currentUserService, router);
+        super(dialogService, authService, currentUserService, routingService);
     }
 
     afterInit(): void {
@@ -65,10 +65,7 @@ export class SpDataExplorerDataViewOverviewComponent extends SpDataExplorerOverv
     }
 
     openDataView(dataView: DataExplorerWidgetModel, editMode: boolean): void {
-        this.router.navigate(
-            ['dataexplorer', 'data-view', dataView.elementId],
-            { queryParams: { editMode } },
-        );
+        this.routingService.navigateToDataView(editMode, dataView.elementId);
     }
 
     deleteDataView(dataView: DataExplorerWidgetModel) {
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
index f2fb845c8a..81b53324b8 100644
--- 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
@@ -28,7 +28,7 @@
             mat-button
             mat-raised-button
             color="accent"
-            data-cy="open-new-data-view-dialog"
+            data-cy="open-new-dashboard-dialog"
             (click)="openNewDashboardDialog()"
             class="mr-10"
             *ngIf="hasDataExplorerWritePrivileges"
@@ -40,6 +40,7 @@
             mat-button
             mat-raised-button
             color="accent"
+            data-cy="open-new-data-view"
             (click)="createNewDataView()"
             class="mr-10"
             *ngIf="hasDataExplorerWritePrivileges"
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
index 151daee106..45d057adc4 100644
--- 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
@@ -28,7 +28,7 @@ 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';
+import { DataExplorerRoutingService } from '../../services/data-explorer-routing.service';
 
 @Component({
     selector: 'sp-data-explorer-overview',
@@ -45,9 +45,9 @@ export class DataExplorerOverviewComponent extends SpDataExplorerOverviewDirecti
         private dataExplorerDashboardService: DataExplorerDashboardService,
         authService: AuthService,
         currentUserService: CurrentUserService,
-        router: Router,
+        routingService: DataExplorerRoutingService,
     ) {
-        super(dialogService, authService, currentUserService, router);
+        super(dialogService, authService, currentUserService, routingService);
     }
 
     afterInit(): void {
@@ -66,9 +66,7 @@ export class DataExplorerOverviewComponent extends SpDataExplorerOverviewDirecti
     }
 
     createNewDataView(): void {
-        this.router.navigate(['dataexplorer', 'data-view'], {
-            queryParams: { editMode: true },
-        });
+        this.routingService.navigateToDataView(true);
     }
 
     openDataViewModificationDialog(createMode: boolean, dashboard: Dashboard) {
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
index 909bf51903..527d43a753 100644
--- 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
@@ -22,7 +22,7 @@ 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';
+import { DataExplorerRoutingService } from '../../services/data-explorer-routing.service';
 
 @Directive()
 export abstract class SpDataExplorerOverviewDirective
@@ -39,7 +39,7 @@ export abstract class SpDataExplorerOverviewDirective
         public dialogService: DialogService,
         protected authService: AuthService,
         protected currentUserService: CurrentUserService,
-        protected router: Router,
+        protected routingService: DataExplorerRoutingService,
     ) {}
 
     ngOnInit() {
diff --git a/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.html b/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.html
deleted file mode 100644
index 0d04478e00..0000000000
--- a/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.html
+++ /dev/null
@@ -1,230 +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
-    [backLinkTarget]="['dataexplorer']"
-    [showBackLink]="true"
-    *ngIf="dashboardLoaded"
->
-    <div nav fxFlex="100">
-        <div
-            class="data-explorer-options-item"
-            fxLayoutAlign="start center"
-            fxLayout="row"
-            *ngIf="editMode"
-        >
-            <button
-                mat-icon-button
-                color="accent"
-                matTooltip="Save"
-                class="edit-menu-btn"
-                (click)="persistDashboardChanges()"
-                data-cy="save-data-explorer-widget-btn"
-            >
-                <mat-icon>save</mat-icon>
-            </button>
-            <button
-                mat-icon-button
-                color="accent"
-                matTooltip="Discard"
-                class="mat-basic mr-10 edit-menu-btn"
-                (click)="discardChanges()"
-            >
-                <i class="material-icons">undo</i>
-            </button>
-            <button
-                mat-icon-button
-                matTooltip="Add widget"
-                color="accent"
-                class="edit-menu-btn"
-                (click)="createWidget()"
-                [disabled]="!editMode"
-                data-cy="add-new-widget"
-            >
-                <i class="material-icons">add</i>
-            </button>
-        </div>
-        <div
-            class="data-explorer-options-item"
-            fxLayoutAlign="start center"
-            fxLayout="row"
-        >
-            <button
-                mat-icon-button
-                [matMenuTriggerFor]="menu"
-                aria-label="View mode"
-                matTooltip="View mode"
-            >
-                <mat-icon
-                    >{{ viewMode === 'grid' ? 'grid_view' : 'web_asset' }}
-                </mat-icon>
-            </button>
-            <mat-menu #menu="matMenu">
-                <button mat-menu-item (click)="viewMode = 'grid'">
-                    <mat-icon>grid_view</mat-icon>
-                    <span>Grid</span>
-                </button>
-                <button mat-menu-item (click)="viewMode = 'slide'">
-                    <mat-icon>web_asset</mat-icon>
-                    <span>Slides</span>
-                </button>
-            </mat-menu>
-        </div>
-        <div
-            class="data-explorer-options-item"
-            style="margin-right: 0"
-            fxLayoutAlign="end center"
-            fxFlex
-            fxLayout="row"
-        >
-            <sp-time-range-selector
-                *ngIf="editMode || timeRangeVisible"
-                (dateRangeEmitter)="updateDateRange($event)"
-                [dateRange]="timeSettings"
-            >
-            </sp-time-range-selector>
-
-            <button
-                mat-icon-button
-                [matMenuTriggerFor]="optMenu"
-                aria-label="Options"
-                data-cy="options-data-explorer"
-            >
-                <mat-icon>more_vert</mat-icon>
-            </button>
-            <mat-menu #optMenu="matMenu">
-                <button
-                    mat-menu-item
-                    (click)="triggerEditMode()"
-                    *ngIf="!editMode && hasDataExplorerWritePrivileges"
-                    data-cy="options-edit-dashboard"
-                >
-                    <mat-icon>edit</mat-icon>
-                    <span>Edit dashboard</span>
-                </button>
-                <button
-                    mat-menu-item
-                    (click)="timeRangeVisible = true"
-                    *ngIf="!editMode && !timeRangeVisible"
-                >
-                    <mat-icon>alarm_on</mat-icon>
-                    <span>Show time range selector</span>
-                </button>
-                <button
-                    mat-menu-item
-                    (click)="timeRangeVisible = false"
-                    *ngIf="!editMode && timeRangeVisible"
-                >
-                    <mat-icon>alarm_off</mat-icon>
-                    <span>Hide time range selector</span>
-                </button>
-                <button
-                    mat-menu-item
-                    *ngIf="hasDataExplorerDeletePrivileges"
-                    (click)="deleteDashboard(dashboard)"
-                >
-                    <mat-icon>clear</mat-icon>
-                    <span>Delete dashboard</span>
-                </button>
-            </mat-menu>
-        </div>
-    </div>
-
-    <div fxFlex="100" fxLayout="column">
-        <mat-drawer-container
-            class="designer-panel-container h-100 dashboard-grid"
-        >
-            <mat-drawer
-                #designerDrawer
-                [opened]="showDesignerPanel"
-                (opened)="triggerResize()"
-                (closed)="triggerResize()"
-                mode="side"
-                position="end"
-                class="designer-panel"
-            >
-                <div fxLayout="column" fxFlex="100">
-                    <sp-data-explorer-designer-panel
-                        #designerPanel
-                        [currentlyConfiguredWidget]="currentlyConfiguredWidget"
-                        [dataLakeMeasure]="dataLakeMeasure"
-                        [newWidgetMode]="newWidgetMode"
-                        (addWidgetEmitter)="addWidget($event)"
-                        (closeDesignerPanelEmitter)="closeDesignerPanel()"
-                        fxFlex="100"
-                    >
-                    </sp-data-explorer-designer-panel>
-                </div>
-            </mat-drawer>
-            <mat-drawer-content class="h-100 dashboard-grid">
-                <div
-                    *ngIf="showEditingHelpInfo"
-                    fxFlex="100"
-                    fxLayout="column"
-                    fxLayoutAlign="center center"
-                >
-                    <h4>
-                        This data view is empty and doesn't contain any widgets.
-                    </h4>
-                    <button
-                        mat-button
-                        mat-raised-button
-                        color="accent"
-                        *ngIf="hasDataExplorerWritePrivileges"
-                        (click)="triggerEditMode()"
-                    >
-                        <mat-icon>add</mat-icon>
-                        Add widget
-                    </button>
-                </div>
-                <sp-data-explorer-dashboard-grid
-                    #dashboardGrid
-                    *ngIf="!showEditingHelpInfo && viewMode === 'grid'"
-                    [editMode]="editMode"
-                    [dashboard]="dashboard"
-                    [timeSettings]="timeSettings"
-                    [currentlyConfiguredWidgetId]="currentlyConfiguredWidgetId"
-                    (configureWidgetCallback)="
-                        updateCurrentlyConfiguredWidget($event)
-                    "
-                    (updateCallback)="updateAndQueueItemForDeletion($event)"
-                    (deleteCallback)="removeAndQueueItemForDeletion($event)"
-                    (startEditModeEmitter)="startEditMode($event)"
-                    class="h-100 dashboard-grid"
-                >
-                </sp-data-explorer-dashboard-grid>
-                <sp-data-explorer-dashboard-slide-view
-                    class="h-100 dashboard-grid"
-                    #dashboardSlide
-                    [editMode]="editMode"
-                    [dashboard]="dashboard"
-                    [timeSettings]="timeSettings"
-                    [currentlyConfiguredWidgetId]="currentlyConfiguredWidgetId"
-                    (configureWidgetCallback)="
-                        updateCurrentlyConfiguredWidget($event)
-                    "
-                    (updateCallback)="updateAndQueueItemForDeletion($event)"
-                    (deleteCallback)="removeAndQueueItemForDeletion($event)"
-                    (startEditModeEmitter)="startEditMode($event)"
-                    *ngIf="!showEditingHelpInfo && viewMode === 'slide'"
-                >
-                </sp-data-explorer-dashboard-slide-view>
-            </mat-drawer-content>
-        </mat-drawer-container>
-    </div>
-</sp-basic-view>
diff --git a/ui/src/app/data-explorer/components/widget-view/abstract-widget-view.directive.ts b/ui/src/app/data-explorer/components/widget-view/abstract-widget-view.directive.ts
index be0a6b300e..8c1bab95d3 100644
--- a/ui/src/app/data-explorer/components/widget-view/abstract-widget-view.directive.ts
+++ b/ui/src/app/data-explorer/components/widget-view/abstract-widget-view.directive.ts
@@ -58,10 +58,6 @@ export abstract class AbstractWidgetViewDirective {
 
     @Output() deleteCallback: EventEmitter<DataExplorerWidgetModel> =
         new EventEmitter<DataExplorerWidgetModel>();
-    @Output() updateCallback: EventEmitter<DataExplorerWidgetModel> =
-        new EventEmitter<DataExplorerWidgetModel>();
-    @Output() configureWidgetCallback: EventEmitter<DataExplorerWidgetModel> =
-        new EventEmitter<DataExplorerWidgetModel>();
     @Output() startEditModeEmitter: EventEmitter<DataExplorerWidgetModel> =
         new EventEmitter<DataExplorerWidgetModel>();
 
@@ -105,13 +101,6 @@ export abstract class AbstractWidgetViewDirective {
                 this.processWidget(r);
                 this.onWidgetsAvailable();
                 this.widgetsAvailable = true;
-                if (this.dashboard.widgets.length > 0 && this.editMode) {
-                    this.startEditModeEmitter.emit(
-                        this.configuredWidgets.get(
-                            this.dashboard.widgets[0].id,
-                        ),
-                    );
-                }
             });
         });
     }
@@ -154,12 +143,9 @@ export abstract class AbstractWidgetViewDirective {
         this.deleteCallback.emit(widget);
     }
 
-    propagateItemUpdate(dashboardWidget: DataExplorerWidgetModel) {
-        this.updateCallback.emit(dashboardWidget);
-    }
+    propagateItemUpdate(dashboardWidget: DataExplorerWidgetModel) {}
 
     propagateWidgetSelection(configuredWidget: DataExplorerWidgetModel) {
-        this.configureWidgetCallback.emit(configuredWidget);
         if (configuredWidget) {
             this.currentlyConfiguredWidgetId = configuredWidget.elementId;
         } else {
@@ -168,10 +154,6 @@ export abstract class AbstractWidgetViewDirective {
         this.onOptionsChanged();
     }
 
-    selectFirstWidgetForEditing(widgetId: string): void {
-        this.startEditModeEmitter.emit(this.configuredWidgets.get(widgetId));
-    }
-
     abstract onOptionsChanged(): void;
 
     abstract onWidgetsAvailable(): void;
diff --git a/ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.html b/ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.html
index 59cd269f65..1fd05d2a36 100644
--- a/ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.html
+++ b/ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.html
@@ -30,14 +30,11 @@
             <sp-data-explorer-dashboard-widget
                 [ngStyle]="{ height: gridsterItemComponent.height - 13 + 'px' }"
                 [timeSettings]="timeSettings"
-                (updateCallback)="propagateItemUpdate($event)"
                 (deleteCallback)="propagateItemRemoval($event)"
-                (configureWidgetCallback)="propagateWidgetSelection($event)"
                 (startEditModeEmitter)="startEditMode($event)"
                 [dashboardItem]="item"
                 [configuredWidget]="configuredWidgets.get(item.id)"
                 [dataLakeMeasure]="dataLakeMeasures.get(item.id)"
-                [currentlyConfiguredWidgetId]="currentlyConfiguredWidgetId"
                 [editMode]="editMode"
                 [gridMode]="true"
                 [gridsterItemComponent]="gridsterItemComponent"
diff --git a/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.html b/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.html
index 9331289194..58797ecddc 100644
--- a/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.html
+++ b/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.html
@@ -53,14 +53,11 @@
                         height: gridsterItemComponent.height - 15 + 'px'
                     }"
                     [timeSettings]="timeSettings"
-                    (updateCallback)="propagateItemUpdate($event)"
                     (deleteCallback)="propagateItemRemoval($event)"
-                    (configureWidgetCallback)="propagateWidgetSelection($event)"
                     (startEditModeEmitter)="startEditMode($event)"
                     [dashboardItem]="currentDashboardItem"
                     [configuredWidget]="currentWidget"
                     [dataLakeMeasure]="currentMeasure"
-                    [currentlyConfiguredWidgetId]="currentlyConfiguredWidgetId"
                     [editMode]="editMode"
                     [gridMode]="false"
                     [gridsterItemComponent]="gridsterItemComponent"
diff --git a/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.ts b/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.ts
index 4c762a510f..b6effac6a4 100644
--- a/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.ts
+++ b/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.ts
@@ -70,12 +70,6 @@ export class DataExplorerDashboardSlideViewComponent
                 index
             ] as unknown as DashboardItem;
             this.currentlyConfiguredWidgetId = widgetId;
-
-            // Opens the design panel for the current widget when in edit mode
-            if (this.editMode) {
-                this.startEditModeEmitter.emit(this.currentWidget);
-            }
-
             this.displayWidget = true;
         });
     }
diff --git a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html
index f2a051edab..fa9617a0ed 100644
--- a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html
+++ b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.html
@@ -24,11 +24,8 @@
             color: configuredWidget.baseAppearanceConfig.textColor,
             height: gridsterItemComponent.height - 13 + 'px',
             border:
-                editMode &&
-                currentlyConfiguredWidgetId === configuredWidget.elementId
-                    ? '4px solid var(--color-accent)'
-                    : '2px solid ' +
-                      configuredWidget.baseAppearanceConfig.backgroundColor
+                '2px solid ' +
+                configuredWidget.baseAppearanceConfig.backgroundColor
         }"
         [attr.data-cy]="
             'widget-' + configuredWidget.baseAppearanceConfig.widgetTitle
@@ -68,7 +65,7 @@
                     [matMenuTriggerFor]="menu"
                     aria-label="More options"
                     matTooltip="More options"
-                    *ngIf="!editMode"
+                    *ngIf="!editMode && !dataViewMode"
                     [attr.data-cy]="
                         'more-options-' +
                         configuredWidget.baseAppearanceConfig.widgetTitle.replaceAll(
@@ -114,28 +111,6 @@
                 >
                     <mat-icon>get_app</mat-icon>
                 </button>
-                <button
-                    mat-icon-button
-                    [class.mat-raised-button]="
-                        currentlyConfiguredWidgetId ===
-                        configuredWidget.elementId
-                    "
-                    (click)="triggerWidgetEditMode()"
-                    *ngIf="editMode"
-                    [color]="
-                        currentlyConfiguredWidgetId ===
-                        configuredWidget.elementId
-                            ? 'accent'
-                            : ''
-                    "
-                    matTooltip="Edit widget"
-                    [attr.data-cy]="
-                        'edit-' +
-                        configuredWidget.baseAppearanceConfig.widgetTitle
-                    "
-                >
-                    <mat-icon>edit</mat-icon>
-                </button>
                 <button
                     mat-icon-button
                     (click)="removeWidget()"
diff --git a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts
index 468c266931..18fcd0c125 100644
--- a/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts
+++ b/ui/src/app/data-explorer/components/widget/data-explorer-dashboard-widget.component.ts
@@ -30,14 +30,11 @@ import {
 import { GridsterItemComponent } from 'angular-gridster2';
 import {
     DashboardItem,
-    DataExplorerDataConfig,
     DataExplorerWidgetModel,
     DataLakeMeasure,
-    DateRange,
     SpLogMessage,
     TimeSettings,
 } from '@streampipes/platform-services';
-import { DataDownloadDialogComponent } from '../../../core-ui/data-download-dialog/data-download-dialog.component';
 import { interval, Subscription } from 'rxjs';
 import { takeWhile } from 'rxjs/operators';
 import { DataExplorerWidgetRegistry } from '../../registry/data-explorer-widget-registry';
@@ -45,12 +42,9 @@ import { WidgetDirective } from './widget.directive';
 import { WidgetTypeService } from '../../services/widget-type.service';
 import { AuthService } from '../../../services/auth.service';
 import { UserPrivilege } from '../../../_enums/user-privilege.enum';
-import {
-    CurrentUserService,
-    DialogService,
-    PanelType,
-} from '@streampipes/shared-ui';
+import { CurrentUserService } from '@streampipes/shared-ui';
 import { BaseWidgetData } from '../../models/dataview-dashboard.model';
+import { DataExplorerDashboardService } from '../../services/data-explorer-dashboard.service';
 
 @Component({
     selector: 'sp-data-explorer-dashboard-widget',
@@ -71,10 +65,10 @@ export class DataExplorerDashboardWidgetComponent implements OnInit, OnDestroy {
     editMode: boolean;
 
     @Input()
-    gridsterItemComponent: GridsterItemComponent;
+    dataViewMode = false;
 
     @Input()
-    currentlyConfiguredWidgetId: string;
+    gridsterItemComponent: GridsterItemComponent;
 
     @Input()
     previewMode = false;
@@ -90,17 +84,11 @@ export class DataExplorerDashboardWidgetComponent implements OnInit, OnDestroy {
 
     @Output() deleteCallback: EventEmitter<DataExplorerWidgetModel> =
         new EventEmitter<DataExplorerWidgetModel>();
-    @Output() updateCallback: EventEmitter<DataExplorerWidgetModel> =
-        new EventEmitter<DataExplorerWidgetModel>();
-    @Output() configureWidgetCallback: EventEmitter<DataExplorerWidgetModel> =
-        new EventEmitter<DataExplorerWidgetModel>();
     @Output() startEditModeEmitter: EventEmitter<DataExplorerWidgetModel> =
         new EventEmitter<DataExplorerWidgetModel>();
 
     title = '';
     widgetLoaded = false;
-
-    msCounter = interval(10);
     timerActive = false;
     loadingTime = 0;
 
@@ -118,7 +106,7 @@ export class DataExplorerDashboardWidgetComponent implements OnInit, OnDestroy {
 
     constructor(
         private widgetRegistryService: DataExplorerWidgetRegistry,
-        private dialogService: DialogService,
+        private dashboardService: DataExplorerDashboardService,
         private componentFactoryResolver: ComponentFactoryResolver,
         private widgetTypeService: WidgetTypeService,
         private authService: AuthService,
@@ -206,37 +194,10 @@ export class DataExplorerDashboardWidgetComponent implements OnInit, OnDestroy {
         this.deleteCallback.emit(this.configuredWidget);
     }
 
-    downloadDataAsFile() {
-        this.dialogService.open(DataDownloadDialogComponent, {
-            panelType: PanelType.SLIDE_IN_PANEL,
-            title: 'Download data',
-            width: '50vw',
-            data: {
-                dataDownloadDialogModel: {
-                    dataExplorerDateRange: DateRange.fromTimeSettings(
-                        this.timeSettings,
-                    ),
-                    dataExplorerDataConfig: this.configuredWidget
-                        .dataConfig as DataExplorerDataConfig,
-                },
-            },
-        });
-    }
-
     startEditMode() {
         this.startEditModeEmitter.emit(this.configuredWidget);
     }
 
-    triggerWidgetEditMode() {
-        if (
-            this.currentlyConfiguredWidgetId === this.configuredWidget.elementId
-        ) {
-            this.configureWidgetCallback.emit();
-        } else {
-            this.configureWidgetCallback.emit(this.configuredWidget);
-        }
-    }
-
     startLoadingTimer() {
         this.timerActive = true;
         this.intervalSubscription = interval(100)
@@ -254,4 +215,11 @@ export class DataExplorerDashboardWidgetComponent implements OnInit, OnDestroy {
     handleTimer(start: boolean) {
         start ? this.startLoadingTimer() : this.stopLoadingTimer();
     }
+
+    downloadDataAsFile(): void {
+        this.dashboardService.downloadDataAsFile(
+            this.timeSettings,
+            this.configuredWidget,
+        );
+    }
 }
diff --git a/ui/src/app/data-explorer/data-explorer-panel.can-deactivate.guard.ts b/ui/src/app/data-explorer/data-explorer-panel.can-deactivate.guard.ts
index 1c51438c29..60e339dbea 100644
--- a/ui/src/app/data-explorer/data-explorer-panel.can-deactivate.guard.ts
+++ b/ui/src/app/data-explorer/data-explorer-panel.can-deactivate.guard.ts
@@ -17,7 +17,7 @@
  */
 
 import { Injectable } from '@angular/core';
-import { DataExplorerDashboardPanelComponent } from './components/panel/data-explorer-dashboard-panel.component';
+import { DataExplorerDashboardPanelComponent } from './components/dashboard/data-explorer-dashboard-panel.component';
 import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
 import { Observable } from 'rxjs';
 
@@ -28,6 +28,10 @@ export class DataExplorerPanelCanDeactivateGuard {
         route: ActivatedRouteSnapshot,
         state: RouterStateSnapshot,
     ): Observable<boolean> | boolean {
-        return component.confirmLeaveDashboard(route, state);
+        if (!state.root.queryParams.omitConfirm === undefined) {
+            return component.confirmLeaveDashboard(route, state);
+        } else {
+            return true;
+        }
     }
 }
diff --git a/ui/src/app/data-explorer/data-explorer.module.ts b/ui/src/app/data-explorer/data-explorer.module.ts
index 44b8ab9baf..62dc60706a 100644
--- a/ui/src/app/data-explorer/data-explorer.module.ts
+++ b/ui/src/app/data-explorer/data-explorer.module.ts
@@ -38,7 +38,7 @@ 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 { DataExplorerOverviewComponent } from './components/overview/data-explorer-overview.component';
-import { DataExplorerDashboardPanelComponent } from './components/panel/data-explorer-dashboard-panel.component';
+import { DataExplorerDashboardPanelComponent } from './components/dashboard/data-explorer-dashboard-panel.component';
 import { TimeRangeSelectorComponent } from './components/time-selector/timeRangeSelector.component';
 import { DataExplorerDashboardWidgetComponent } from './components/widget/data-explorer-dashboard-widget.component';
 import { ImageWidgetComponent } from './components/widgets/image/image-widget.component';
@@ -51,22 +51,22 @@ import { SelectColorPropertiesComponent } from './components/widgets/utils/selec
 import { DataExplorerEditDataViewDialogComponent } from './dialogs/edit-dashboard/data-explorer-edit-data-view-dialog.component';
 import { GroupConfigurationComponent } from './components/widgets/utils/group-configuration/group-configuration.component';
 import { MatSlideToggleModule } from '@angular/material/slide-toggle';
-import { DataExplorerDesignerPanelComponent } from './components/designer-panel/data-explorer-designer-panel.component';
+import { DataExplorerDesignerPanelComponent } from './components/data-view/data-view-designer-panel/data-explorer-designer-panel.component';
 import { TableWidgetConfigComponent } from './components/widgets/table/config/table-widget-config.component';
 import { MapWidgetComponent } from './components/widgets/map/map-widget.component';
 import { MapWidgetConfigComponent } from './components/widgets/map/config/map-widget-config.component';
 import { HeatmapWidgetConfigComponent } from './components/widgets/heatmap/config/heatmap-widget-config.component';
-import { DataExplorerWidgetAppearanceSettingsComponent } from './components/designer-panel/appearance-settings/data-explorer-widget-appearance-settings.component';
-import { DataExplorerWidgetDataSettingsComponent } from './components/designer-panel/data-settings/data-explorer-widget-data-settings.component';
+import { DataExplorerWidgetAppearanceSettingsComponent } from './components/data-view/data-view-designer-panel/appearance-settings/data-explorer-widget-appearance-settings.component';
+import { DataExplorerWidgetDataSettingsComponent } from './components/data-view/data-view-designer-panel/data-settings/data-explorer-widget-data-settings.component';
 import { TimeSeriesChartWidgetConfigComponent } from './components/widgets/time-series-chart/config/time-series-chart-widget-config.component';
 import { ImageWidgetConfigComponent } from './components/widgets/image/config/image-widget-config.component';
 import { IndicatorWidgetConfigComponent } from './components/widgets/indicator/config/indicator-chart-widget-config.component';
-import { FieldSelectionPanelComponent } from './components/designer-panel/data-settings/field-selection-panel/field-selection-panel.component';
-import { FieldSelectionComponent } from './components/designer-panel/data-settings/field-selection/field-selection.component';
-import { FilterSelectionPanelComponent } from './components/designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component';
+import { FieldSelectionPanelComponent } from './components/data-view/data-view-designer-panel/data-settings/field-selection-panel/field-selection-panel.component';
+import { FieldSelectionComponent } from './components/data-view/data-view-designer-panel/data-settings/field-selection/field-selection.component';
+import { FilterSelectionPanelComponent } from './components/data-view/data-view-designer-panel/data-settings/filter-selection-panel/filter-selection-panel.component';
 import { SelectPropertyComponent } from './components/widgets/utils/select-property/select-property.component';
-import { DataExplorerVisualisationSettingsComponent } from './components/designer-panel/visualisation-settings/data-explorer-visualisation-settings.component';
-import { GroupSelectionPanelComponent } from './components/designer-panel/data-settings/group-selection-panel/group-selection-panel.component';
+import { DataExplorerVisualisationSettingsComponent } from './components/data-view/data-view-designer-panel/visualisation-settings/data-explorer-visualisation-settings.component';
+import { GroupSelectionPanelComponent } from './components/data-view/data-view-designer-panel/data-settings/group-selection-panel/group-selection-panel.component';
 import { WidgetDirective } from './components/widget/widget.directive';
 import { CorrelationWidgetConfigComponent } from './components/widgets/correlation-chart/config/correlation-chart-widget-config.component';
 import { TooMuchDataComponent } from './components/widgets/utils/too-much-data/too-much-data.component';
@@ -117,6 +117,10 @@ import { SpDataExplorerDataViewOverviewComponent } from './components/overview/d
 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';
+import { DataExplorerDataViewSelectionComponent } from './components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-selection.component';
+import { DataExplorerDashboardWidgetSelectionPanelComponent } from './components/dashboard/dashboard-widget-selection-panel/dashboard-widget-selection-panel.component';
+import { DataExplorerDataViewPreviewComponent } from './components/dashboard/dashboard-widget-selection-panel/data-view-selection/data-view-preview/data-view-preview.component';
+import { DataExplorerDashboardToolbarComponent } from './components/dashboard/dashboard-toolbar/dashboard-toolbar.component';
 
 @NgModule({
     imports: [
@@ -201,7 +205,11 @@ import { DataExplorerDataViewToolbarComponent } from './components/data-view/dat
         DataExplorerOverviewComponent,
         DataExplorerDashboardPanelComponent,
         DataExplorerDashboardSlideViewComponent,
+        DataExplorerDashboardToolbarComponent,
         DataExplorerDashboardWidgetComponent,
+        DataExplorerDashboardWidgetSelectionPanelComponent,
+        DataExplorerDataViewPreviewComponent,
+        DataExplorerDataViewSelectionComponent,
         DataExplorerDesignerPanelComponent,
         DataExplorerEditDataViewDialogComponent,
         DataExplorerWidgetAppearanceSettingsComponent,
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
index aefed314e1..e7177e9fa1 100644
--- a/ui/src/app/data-explorer/services/data-explorer-dashboard.service.ts
+++ b/ui/src/app/data-explorer/services/data-explorer-dashboard.service.ts
@@ -17,9 +17,16 @@
  */
 
 import { Injectable } from '@angular/core';
-import { Dashboard } from '@streampipes/platform-services';
+import {
+    Dashboard,
+    DataExplorerDataConfig,
+    DataExplorerWidgetModel,
+    DateRange,
+    TimeSettings,
+} from '@streampipes/platform-services';
 import { DataExplorerEditDataViewDialogComponent } from '../dialogs/edit-dashboard/data-explorer-edit-data-view-dialog.component';
 import { DialogService, PanelType } from '@streampipes/shared-ui';
+import { DataDownloadDialogComponent } from '../../core-ui/data-download-dialog/data-download-dialog.component';
 
 @Injectable({ providedIn: 'root' })
 export class DataExplorerDashboardService {
@@ -39,4 +46,23 @@ export class DataExplorerDashboardService {
             },
         );
     }
+
+    downloadDataAsFile(
+        timeSettings: TimeSettings,
+        dataView: DataExplorerWidgetModel,
+    ) {
+        this.dialogService.open(DataDownloadDialogComponent, {
+            panelType: PanelType.SLIDE_IN_PANEL,
+            title: 'Download data',
+            width: '50vw',
+            data: {
+                dataDownloadDialogModel: {
+                    dataExplorerDateRange:
+                        DateRange.fromTimeSettings(timeSettings),
+                    dataExplorerDataConfig:
+                        dataView.dataConfig as DataExplorerDataConfig,
+                },
+            },
+        });
+    }
 }
diff --git a/ui/src/app/data-explorer/services/data-explorer-routing.service.ts b/ui/src/app/data-explorer/services/data-explorer-routing.service.ts
new file mode 100644
index 0000000000..d6ed9d7527
--- /dev/null
+++ b/ui/src/app/data-explorer/services/data-explorer-routing.service.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 { Injectable } from '@angular/core';
+import { Router } from '@angular/router';
+
+@Injectable({ providedIn: 'root' })
+export class DataExplorerRoutingService {
+    private dataViewPath = ['dataexplorer', 'data-view'];
+    private dashboardPath = ['dataexplorer', 'dashboard'];
+
+    constructor(private router: Router) {}
+
+    navigateToOverview(omitConfirm: boolean = false): void {
+        this.router.navigate(['dataexplorer'], { state: { omitConfirm } });
+    }
+
+    navigateToDataView(
+        editMode: boolean,
+        dataViewElementId?: string,
+        newTab = false,
+    ) {
+        return this.navigate(
+            editMode,
+            this.dataViewPath,
+            dataViewElementId,
+            newTab,
+        );
+    }
+
+    navigateToDashboard(
+        editMode: boolean,
+        dashboardElementId?: string,
+        newTab = false,
+    ) {
+        return this.navigate(
+            editMode,
+            this.dashboardPath,
+            dashboardElementId,
+            newTab,
+        );
+    }
+
+    private navigate(
+        editMode: boolean,
+        initialPath: string[],
+        resourceElementId?: string,
+        openInNewTab = false,
+    ) {
+        const queryParams = editMode ? { editMode: true } : {};
+        const navigationExtras = {
+            queryParams,
+        };
+
+        // Generate the URL
+        const urlTree = this.router.createUrlTree(
+            this.getPath(initialPath, resourceElementId),
+            navigationExtras,
+        );
+        const url = this.router.serializeUrl(urlTree);
+
+        if (openInNewTab) {
+            window.open('/#' + url, '_blank');
+        } else {
+            // Navigate using the router
+            return this.router.navigateByUrl(urlTree);
+        }
+    }
+
+    private getPath(
+        initialPath: string[],
+        resourceElementId?: string,
+    ): string[] {
+        return resourceElementId
+            ? [...initialPath, resourceElementId]
+            : initialPath;
+    }
+}