You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by ri...@apache.org on 2022/05/28 20:35:00 UTC

[incubator-streampipes] branch dev updated: [STREAMPIPES-539] Support slide view in data explorer

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

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


The following commit(s) were added to refs/heads/dev by this push:
     new 42e4f825d [STREAMPIPES-539] Support slide view in data explorer
42e4f825d is described below

commit 42e4f825deb93022cdc29a2714cfb08cfb9b73d8
Author: Dominik Riemer <do...@gmail.com>
AuthorDate: Sat May 28 22:24:52 2022 +0200

    [STREAMPIPES-539] Support slide view in data explorer
---
 .../data-explorer-designer-panel.component.ts      |   4 +-
 .../data-explorer-dashboard-panel.component.html   | 104 ++++++++++-----
 .../data-explorer-dashboard-panel.component.ts     |  43 ++++---
 .../abstract-widget-view.directive.ts}             | 143 ++++++++-------------
 .../data-explorer-dashboard-grid.component.html    |   3 +-
 .../data-explorer-dashboard-grid.component.scss    |   0
 .../data-explorer-dashboard-grid.component.ts      | 101 +++++++++++++++
 ...ta-explorer-dashboard-slide-view.component.html |  47 +++++++
 ...a-explorer-dashboard-slide-view.component.scss} |  31 +++--
 ...data-explorer-dashboard-slide-view.component.ts | 104 +++++++++++++++
 .../data-explorer-dashboard-widget.component.html  |   4 +-
 .../data-explorer-dashboard-widget.component.ts    |  22 ++--
 .../base/base-data-explorer-widget.directive.ts    |  34 +++--
 .../widgets/base/data-explorer-widget-data.ts      |   4 +-
 .../time-series-chart-widget.component.ts          |  20 +--
 ui/src/app/data-explorer/data-explorer.module.ts   |   4 +-
 16 files changed, 480 insertions(+), 188 deletions(-)

diff --git a/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.ts b/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.ts
index 94af4fac1..e2e814aac 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.ts
+++ b/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.ts
@@ -51,7 +51,9 @@ export class DataExplorerDesignerPanelComponent implements OnInit {
     // Set default name to the measure name
     if (this.currentlyConfiguredWidget.dataConfig.sourceConfigs.length > 0) {
       this.currentlyConfiguredWidget.baseAppearanceConfig.widgetTitle =
-        this.currentlyConfiguredWidget.dataConfig.sourceConfigs[0].measureName;
+        this.currentlyConfiguredWidget.dataConfig.sourceConfigs[0].measureName
+        + ' - '
+        + this.currentlyConfiguredWidget.widgetType;
     }
 
     this.addWidgetEmitter.emit({ a: this.dataLakeMeasure, b: this.currentlyConfiguredWidget });
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
index 77cec39d2..8fb64a0c4 100644
--- 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
@@ -22,7 +22,7 @@
             <div class="data-explorer-options-item pl-10"
                  fxLayout="row"
                  fxLayoutAlign="start center"
-                style="border-right: 2px solid var(--color-bg-2)">
+                 style="border-right: 2px solid var(--color-bg-2)">
                 <button mat-button
                         mat-icon-button
                         color="accent"
@@ -34,18 +34,18 @@
             </div>
             <div class="data-explorer-options-item" fxLayoutAlign="start center" fxLayout="row" *ngIf="editMode">
                 <button mat-button mat-icon-button
-                        color="accent" 
-                        matTooltip="Save" 
+                        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-button 
+                <button mat-button
                         mat-icon-button
                         color="accent"
                         matTooltip="Discard"
-                        class="mat-basic mr-10 edit-menu-btn" 
+                        class="mat-basic mr-10 edit-menu-btn"
                         (click)="discardChanges()">
                     <i class="material-icons">undo</i>
                 </button>
@@ -54,28 +54,47 @@
                         matTooltip="Add widget"
                         color="accent"
                         class="edit-menu-btn" (click)="createWidget()"
-                    [disabled]="!editMode" data-cy="add-new-widget">
+                        [disabled]="!editMode" data-cy="add-new-widget">
                     <i class="material-icons">add</i>
                 </button>
             </div>
-            <div class="data-explorer-options-item" style="margin-right: 0" fxLayoutAlign="end center" fxFlex fxLayout="row">
+            <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">
+                                        (dateRangeEmitter)="updateDateRange($event)" [dateRange]="timeSettings">
                 </sp-time-range-selector>
 
-                <button mat-icon-button [matMenuTriggerFor]="menu" aria-label="Options" data-cy="options-data-explorer">
+                <button mat-icon-button [matMenuTriggerFor]="optMenu" aria-label="Options" data-cy="options-data-explorer">
                     <mat-icon>more_vert</mat-icon>
                 </button>
-                <mat-menu #menu="matMenu">
-                    <button mat-menu-item 
-                        (click)="triggerEditMode()"
-                        *ngIf="!editMode && hasDataExplorerWritePrivileges" 
-                        data-cy="options-edit-dashboard">
+                <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" 
+                    <button mat-menu-item
+                            (click)="timeRangeVisible = true"
                             *ngIf="!editMode && !timeRangeVisible">
                         <mat-icon>alarm_on</mat-icon>
                         <span>Show time range selector</span>
@@ -85,7 +104,7 @@
                         <span>Hide time range selector</span>
                     </button>
                     <button mat-menu-item *ngIf="hasDataExplorerDeletePrivileges"
-                        (click)="deleteDashboard(dashboard)">
+                            (click)="deleteDashboard(dashboard)">
                         <mat-icon>clear</mat-icon>
                         <span>Delete dashboard</span>
                     </button>
@@ -96,33 +115,48 @@
 
         <div fxFlex="100" fxLayout="column">
             <mat-drawer-container class="designer-panel-container h-100 dashboard-grid">
-                <mat-drawer #designerDrawer 
-                            [opened]="showDesignerPanel" 
+                <mat-drawer #designerDrawer
+                            [opened]="showDesignerPanel"
                             (opened)="triggerResize()"
-                            (closed)="triggerResize()" 
-                            mode="side" 
-                            position="end" 
+                            (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">
+                                                         [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">
-                    <sp-data-explorer-dashboard-grid #dashboardGrid 
-                        [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 #dashboardGrid
+                                                     *ngIf="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="viewMode === 'slide'">
+                    </sp-data-explorer-dashboard-slide-view>
                 </mat-drawer-content>
             </mat-drawer-container>
         </div>
diff --git a/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.ts b/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.ts
index 86e6d3386..da4c5e49d 100644
--- a/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.ts
+++ b/ui/src/app/data-explorer/components/panel/data-explorer-dashboard-panel.component.ts
@@ -16,32 +16,26 @@
  *
  */
 
-import {
-  Component,
-  EventEmitter,
-  OnInit,
-  Output,
-  ViewChild,
-} from '@angular/core';
+import { Component, EventEmitter, OnInit, Output, ViewChild, } from '@angular/core';
 import { MatDialog } from '@angular/material/dialog';
-import { Observable, zip } from 'rxjs';
-import { DataExplorerDashboardGridComponent } from '../grid/data-explorer-dashboard-grid.component';
+import { combineLatest, Observable, zip } 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,
-  TimeSettings,
   DataExplorerWidgetModel,
   DataLakeMeasure,
-  ClientDashboardItem,
   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, Router } from '@angular/router';
-import { combineLatest } from 'rxjs';
+import { DataExplorerDashboardSlideViewComponent } from '../widget-view/slide-view/data-explorer-dashboard-slide-view.component';
 
 @Component({
   selector: 'sp-data-explorer-dashboard-panel',
@@ -56,6 +50,7 @@ export class DataExplorerDashboardPanelComponent implements OnInit {
    * This is the date range (start, end) to view the data and is set in data-explorer.ts
    */
   timeSettings: TimeSettings;
+  viewMode = 'grid';
 
   editMode = false;
   timeRangeVisible = true;
@@ -65,8 +60,13 @@ export class DataExplorerDashboardPanelComponent implements OnInit {
 
   @ViewChild('dashboardGrid')
   dashboardGrid: DataExplorerDashboardGridComponent;
+
+  @ViewChild('dashboardSlide')
+  dashboardSlide: DataExplorerDashboardSlideViewComponent;
+
   @ViewChild('designerDrawer')
   designerDrawer: MatDrawer;
+
   @ViewChild('designerPanel')
   designerPanel: DataExplorerDesignerPanelComponent;
 
@@ -139,7 +139,11 @@ export class DataExplorerDashboardPanelComponent implements OnInit {
     dashboardItem.x = 0;
     dashboardItem.y = 0;
     this.dashboard.widgets.push(dashboardItem);
-    this.dashboardGrid.loadWidgetConfig(widget._id, true);
+    if (this.viewMode === 'grid') {
+      this.dashboardGrid.loadWidgetConfig(widget._id, true);
+    } else {
+      this.dashboardSlide.loadWidgetConfig(widget._id, true);
+    }
   }
 
   persistDashboardChanges() {
@@ -151,7 +155,11 @@ export class DataExplorerDashboardPanelComponent implements OnInit {
           const observables = this.deleteWidgets();
           zip(...observables).subscribe(() => {
             this.widgetIdsToRemove.forEach((id) => {
-              this.dashboardGrid.configuredWidgets.delete(id);
+              if (this.viewMode === 'grid') {
+                this.dashboardGrid.configuredWidgets.delete(id);
+              } else {
+                this.dashboardSlide.configuredWidgets.delete(id);
+              }
             });
 
             this.afterDashboardChange();
@@ -165,7 +173,11 @@ export class DataExplorerDashboardPanelComponent implements OnInit {
   }
 
   afterDashboardChange() {
-    this.dashboardGrid.updateAllWidgets();
+    if (this.viewMode === 'grid') {
+      this.dashboardGrid.updateAllWidgets();
+    } else {
+      this.dashboardSlide.updateAllWidgets();
+    }
     this.editModeChange.emit(false);
     this.closeDesignerPanel();
   }
@@ -233,6 +245,7 @@ export class DataExplorerDashboardPanelComponent implements OnInit {
 
   triggerEditMode() {
     this.editMode = true;
+    this.editModeChange.emit(true);
   }
 
   createWidget() {
diff --git a/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.ts b/ui/src/app/data-explorer/components/widget-view/abstract-widget-view.directive.ts
similarity index 56%
rename from ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.ts
rename to ui/src/app/data-explorer/components/widget-view/abstract-widget-view.directive.ts
index 45ee85dab..8af0e0564 100644
--- a/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.ts
+++ b/ui/src/app/data-explorer/components/widget-view/abstract-widget-view.directive.ts
@@ -16,44 +16,34 @@
  *
  */
 
+import { Directive, EventEmitter, Input, Output } from '@angular/core';
 import {
-  Component,
-  EventEmitter,
-  Input,
-  OnChanges,
-  OnInit,
-  Output,
-  QueryList,
-  SimpleChanges,
-  ViewChildren
-} from '@angular/core';
-import { GridsterItemComponent, GridType } from 'angular-gridster2';
-import { GridsterInfo } from '../../../dashboard/models/gridster-info.model';
-import { IDataViewDashboardConfig } from '../../models/dataview-dashboard.model';
-import { ResizeService } from '../../services/resize.service';
-import {
-  DataViewDataExplorerService,
   Dashboard,
   DataExplorerWidgetModel,
   DataLakeMeasure,
+  DataViewDataExplorerService,
   TimeSettings
-} from '@streampipes/platform-services';
+} from '../../../../../dist/streampipes/platform-services';
+import { ResizeService } from '../../services/resize.service';
+import { zip } from 'rxjs';
+
+@Directive()
+export abstract class AbstractWidgetViewDirective {
 
-@Component({
-  selector: 'sp-data-explorer-dashboard-grid',
-  templateUrl: './data-explorer-dashboard-grid.component.html',
-  styleUrls: ['./data-explorer-dashboard-grid.component.scss']
-})
-export class DataExplorerDashboardGridComponent implements OnInit, OnChanges {
+  _dashboard: Dashboard;
 
   @Input()
   editMode: boolean;
 
-  _dashboard: Dashboard;
+  @Input()
+  currentlyConfiguredWidgetId: string;
 
   configuredWidgets: Map<string, DataExplorerWidgetModel> = new Map<string, DataExplorerWidgetModel>();
   dataLakeMeasures: Map<string, DataLakeMeasure> = new Map<string, DataLakeMeasure>();
 
+  widgetsAvailable = false;
+  widgetsVisible = true;
+
   /**
    * This is the date range (start, end) to view the data and is set in data-explorer.ts
    */
@@ -65,46 +55,24 @@ export class DataExplorerDashboardGridComponent implements OnInit, OnChanges {
   @Output() configureWidgetCallback: EventEmitter<DataExplorerWidgetModel> = new EventEmitter<DataExplorerWidgetModel>();
   @Output() startEditModeEmitter: EventEmitter<DataExplorerWidgetModel> = new EventEmitter<DataExplorerWidgetModel>();
 
-  options: IDataViewDashboardConfig;
-  loaded = false;
 
-  @Input()
-  currentlyConfiguredWidgetId: string;
-
-  @ViewChildren(GridsterItemComponent) gridsterItemComponents: QueryList<GridsterItemComponent>;
+  constructor(protected resizeService: ResizeService,
+              protected dataViewDataExplorerService: DataViewDataExplorerService) {
 
-  constructor(private resizeService: ResizeService,
-              private dataViewDataExplorerService: DataViewDataExplorerService) {
+  }
 
+  updateAllWidgets() {
+    this.configuredWidgets.forEach((value, key) => {
+      this.dataViewDataExplorerService.updateWidget(value).subscribe(response => {
+        value._rev = response._rev;
+        this.currentlyConfiguredWidgetId = undefined;
+      });
+    });
   }
 
-  ngOnInit(): void {
-    this.options = {
-      disablePushOnDrag: true,
-      draggable: {enabled: this.editMode},
-      gridType: GridType.VerticalFixed,
-      minCols: 8,
-      maxCols: 8,
-      minRows: 4,
-      fixedRowHeight: 100,
-      fixedColWidth: 100,
-      margin: 5,
-      displayGrid: this.editMode ? 'always' : 'none',
-      resizable: {enabled: this.editMode},
-      itemResizeCallback: ((item, itemComponent) => {
-        this.resizeService.notify({
-          gridsterItem: item,
-          gridsterItemComponent: itemComponent
-        } as GridsterInfo);
-      }),
-      itemInitCallback: ((item, itemComponent) => {
-        this.resizeService.notify({
-          gridsterItem: item,
-          gridsterItemComponent: itemComponent
-        } as GridsterInfo);
-        window.dispatchEvent(new Event('resize'));
-      })
-    };
+  startEditMode(value: DataExplorerWidgetModel) {
+    this.startEditModeEmitter.emit(value);
+    this.currentlyConfiguredWidgetId = value._id;
   }
 
   @Input() set dashboard(dashboard: Dashboard) {
@@ -117,29 +85,37 @@ export class DataExplorerDashboardGridComponent implements OnInit, OnChanges {
   }
 
   loadWidgetConfigs() {
-    this.dashboard.widgets.forEach(widget => {
-      this.loadWidgetConfig(widget.id);
+    const observables = this.dashboard.widgets.map(w => this.dataViewDataExplorerService.getWidget(w.id));
+    zip(...observables).subscribe(results => {
+      results.forEach(r => {
+        this.processWidget(r);
+        this.onWidgetsAvailable();
+        this.widgetsAvailable = true;
+      });
     });
-
   }
 
   loadWidgetConfig(widgetId: string, setCurrentlyConfigured?: boolean) {
+    if (!this.isGridView()) {
+      this.widgetsVisible = false;
+    }
     this.dataViewDataExplorerService.getWidget(widgetId).subscribe(response => {
-      this.configuredWidgets.set(widgetId, response);
-      this.dataLakeMeasures.set(widgetId, response.dataConfig.sourceConfigs[0].measure);
+      this.processWidget(response);
       if (setCurrentlyConfigured) {
         this.propagateWidgetSelection(this.configuredWidgets.get(widgetId));
+        if (!this.isGridView()) {
+          this.selectNewWidget(widgetId);
+        }
+      }
+      if (!this.isGridView()) {
+        this.widgetsVisible = true;
       }
     });
   }
 
-  ngOnChanges(changes: SimpleChanges): void {
-    if (changes['editMode'] && this.options) {
-      this.options.draggable.enabled = this.editMode;
-      this.options.resizable.enabled = this.editMode;
-      this.options.displayGrid = this.editMode ? 'always' : 'none';
-      this.options.api.optionsChanged();
-    }
+  processWidget(widget: DataExplorerWidgetModel) {
+    this.configuredWidgets.set(widget._id, widget);
+    this.dataLakeMeasures.set(widget._id, widget.dataConfig.sourceConfigs[0].measure);
   }
 
   propagateItemRemoval(widget: DataExplorerWidgetModel) {
@@ -157,26 +133,17 @@ export class DataExplorerDashboardGridComponent implements OnInit, OnChanges {
     } else {
       this.currentlyConfiguredWidgetId = undefined;
     }
-    this.options.api.optionsChanged();
+    this.onOptionsChanged();
   }
 
-  toggleGrid() {
-    this.options.displayGrid = this.options.displayGrid === 'none' ? 'always' : 'none';
-    this.options.api.optionsChanged();
-  }
+  abstract onOptionsChanged(): void;
+
+  abstract onWidgetsAvailable(): void;
+
+  abstract isGridView(): boolean;
+
+  abstract selectNewWidget(widgetId): void;
 
-  updateAllWidgets() {
-    this.configuredWidgets.forEach((value, key) => {
-      this.dataViewDataExplorerService.updateWidget(value).subscribe(response => {
-        value._rev = response._rev;
-        this.currentlyConfiguredWidgetId = undefined;
-      });
-    });
-  }
 
-  startEditMode(value: DataExplorerWidgetModel) {
-    this.startEditModeEmitter.emit(value);
-    this.currentlyConfiguredWidgetId = value._id;
-  }
 
 }
diff --git a/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.html b/ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.html
similarity index 93%
rename from ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.html
rename to ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.html
index 31fea6810..98bda4f46 100644
--- a/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.html
+++ b/ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.html
@@ -34,8 +34,9 @@
                     [dataLakeMeasure]="dataLakeMeasures.get(item.id)"
                     [currentlyConfiguredWidgetId]="currentlyConfiguredWidgetId"
                     [editMode]="editMode"
+                    [gridMode]="true"
                     [gridsterItemComponent]="gridsterItemComponent"
-                    *ngIf="configuredWidgets.has(item.id) && dataLakeMeasures.has(item.id)"></sp-data-explorer-dashboard-widget>
+                    *ngIf="widgetsAvailable"></sp-data-explorer-dashboard-widget>
         </gridster-item>
     </ng-container>
 </gridster>
diff --git a/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.scss b/ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.scss
similarity index 100%
rename from ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.scss
rename to ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.scss
diff --git a/ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.ts b/ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.ts
new file mode 100644
index 000000000..ccd179c85
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widget-view/grid-view/data-explorer-dashboard-grid.component.ts
@@ -0,0 +1,101 @@
+/*
+ * 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, OnChanges, OnInit, QueryList, SimpleChanges, ViewChildren } from '@angular/core';
+import { GridsterItemComponent, GridType } from 'angular-gridster2';
+import { GridsterInfo } from '../../../../dashboard/models/gridster-info.model';
+import { IDataViewDashboardConfig } from '../../../models/dataview-dashboard.model';
+import { ResizeService } from '../../../services/resize.service';
+import { DataViewDataExplorerService } from '@streampipes/platform-services';
+import { AbstractWidgetViewDirective } from '../abstract-widget-view.directive';
+
+@Component({
+  selector: 'sp-data-explorer-dashboard-grid',
+  templateUrl: './data-explorer-dashboard-grid.component.html',
+  styleUrls: ['./data-explorer-dashboard-grid.component.scss']
+})
+export class DataExplorerDashboardGridComponent extends AbstractWidgetViewDirective implements OnInit, OnChanges {
+
+  options: IDataViewDashboardConfig;
+  loaded = false;
+
+  @ViewChildren(GridsterItemComponent) gridsterItemComponents: QueryList<GridsterItemComponent>;
+
+  constructor(protected resizeService: ResizeService,
+              protected dataViewDataExplorerService: DataViewDataExplorerService) {
+    super(resizeService, dataViewDataExplorerService);
+  }
+
+  ngOnInit(): void {
+    this.options = {
+      disablePushOnDrag: true,
+      draggable: {enabled: this.editMode},
+      gridType: GridType.VerticalFixed,
+      minCols: 8,
+      maxCols: 8,
+      minRows: 4,
+      fixedRowHeight: 100,
+      fixedColWidth: 100,
+      margin: 5,
+      displayGrid: this.editMode ? 'always' : 'none',
+      resizable: {enabled: this.editMode},
+      itemResizeCallback: ((item, itemComponent) => {
+        this.resizeService.notify({
+          gridsterItem: item,
+          gridsterItemComponent: itemComponent
+        } as GridsterInfo);
+      }),
+      itemInitCallback: ((item, itemComponent) => {
+        this.resizeService.notify({
+          gridsterItem: item,
+          gridsterItemComponent: itemComponent
+        } as GridsterInfo);
+        window.dispatchEvent(new Event('resize'));
+      })
+    };
+  }
+
+  ngOnChanges(changes: SimpleChanges): void {
+    if (changes['editMode'] && this.options) {
+      this.options.draggable.enabled = this.editMode;
+      this.options.resizable.enabled = this.editMode;
+      this.options.displayGrid = this.editMode ? 'always' : 'none';
+      this.options.api.optionsChanged();
+    }
+  }
+
+  toggleGrid() {
+    this.options.displayGrid = this.options.displayGrid === 'none' ? 'always' : 'none';
+    this.options.api.optionsChanged();
+  }
+
+  onOptionsChanged() {
+    this.options.api.optionsChanged();
+  }
+
+  onWidgetsAvailable(): void {
+  }
+
+  isGridView(): boolean {
+    return true;
+  }
+
+  selectNewWidget(widgetId): void {
+  }
+
+}
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
new file mode 100644
index 000000000..4f08664c7
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.html
@@ -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.
+  ~
+  -->
+
+<div class="h-100 dashboard-grid" fxLayout="column">
+    <div fxFlex="100px" fxLayout="row" class="selection-box" *ngIf="widgetsAvailable && currentWidget">
+        <div *ngFor="let item of dashboard.widgets; let i = index"
+             [ngClass]="item.id === currentWidget._id ? 'viz-preview viz-preview-selected' : 'viz-preview'"
+             fxLayoutAlign="center center" (click)="selectWidget(i, item.id)">
+            <div fxFlex="100"
+                 fxLayoutAlign="center center">
+                <h5 *ngIf="widgetsVisible">{{configuredWidgets.get(item.id).baseAppearanceConfig.widgetTitle}}</h5>
+            </div>
+        </div>
+    </div>
+    <div class="h-100 dashboard-grid" fxLayout="column" id="slideViewOuter" fxFlex="100">
+        <sp-data-explorer-dashboard-widget
+                [ngStyle]="{height: gridsterItemComponent.height -5 + '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"
+                *ngIf="widgetsAvailable && displayWidget && currentWidget && widgetsVisible"></sp-data-explorer-dashboard-widget>
+    </div>
+</div>
diff --git a/ui/src/app/data-explorer/components/widgets/base/data-explorer-widget-data.ts b/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.scss
similarity index 58%
copy from ui/src/app/data-explorer/components/widgets/base/data-explorer-widget-data.ts
copy to ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.scss
index b6927b1bf..5466c053d 100644
--- a/ui/src/app/data-explorer/components/widgets/base/data-explorer-widget-data.ts
+++ b/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.scss
@@ -16,20 +16,25 @@
  *
  */
 
-import { EventEmitter } from '@angular/core';
-import { GridsterItem, GridsterItemComponent } from 'angular-gridster2';
-import { DataExplorerWidgetModel, DashboardItem, TimeSettings } from '@streampipes/platform-services';
-
-export interface BaseWidgetData<T extends DataExplorerWidgetModel> {
-  removeWidgetCallback: EventEmitter<boolean>;
-  timerCallback: EventEmitter<boolean>;
+.dashboard-grid {
+  display:flex;
+  flex-direction: column;
+  flex: 1 1 100%;
+}
 
-  gridsterItem: GridsterItem;
-  gridsterItemComponent: GridsterItemComponent;
-  editMode: boolean;
+.viz-preview {
+  max-height: 100px;
+  width: 200px;
+  border: 1px solid var(--color-bg-2);
+  cursor: pointer;
+}
 
-  timeSettings: TimeSettings;
+.viz-preview-selected {
+  border: 3px solid var(--color-accent);
+}
 
-  dataViewDashboardItem: DashboardItem;
-  dataExplorerWidget: T;
+.selection-box {
+  border: 1px solid var(--color-accent);
+  overflow-x: auto;
+  margin-bottom: 5px;
 }
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
new file mode 100644
index 000000000..53ab2e019
--- /dev/null
+++ b/ui/src/app/data-explorer/components/widget-view/slide-view/data-explorer-dashboard-slide-view.component.ts
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { AfterViewInit, Component, ElementRef, OnChanges, OnInit, SimpleChanges, ViewChild } from '@angular/core';
+import { AbstractWidgetViewDirective } from '../abstract-widget-view.directive';
+import { ResizeService } from '../../../services/resize.service';
+import {
+  DashboardItem,
+  DataExplorerWidgetModel,
+  DataLakeMeasure,
+  DataViewDataExplorerService
+} from '@streampipes/platform-services';
+
+@Component({
+  selector: 'sp-data-explorer-dashboard-slide-view',
+  templateUrl: './data-explorer-dashboard-slide-view.component.html',
+  styleUrls: ['./data-explorer-dashboard-slide-view.component.scss']
+})
+export class DataExplorerDashboardSlideViewComponent extends AbstractWidgetViewDirective implements OnInit, AfterViewInit, OnChanges {
+
+  selectedWidgetIndex = 0;
+
+  gridsterItemComponent: any = {width: 100, height: 100};
+  previewGridsterItemComponent: any = {width: 200, height: 100};
+
+  currentWidget: DataExplorerWidgetModel;
+  currentMeasure: DataLakeMeasure;
+  currentDashboardItem: DashboardItem;
+
+  displayWidget = false;
+
+  @ViewChild('slideViewOuter') slideViewOuter: ElementRef;
+
+  constructor(protected resizeService: ResizeService,
+              protected dataViewDataExplorerService: DataViewDataExplorerService) {
+    super(resizeService, dataViewDataExplorerService);
+  }
+
+  ngOnChanges(changes: SimpleChanges): void {
+  }
+
+  ngOnInit(): void {
+  }
+
+
+  onOptionsChanged(): void {
+  }
+
+  selectWidget(index: number,
+               widgetId: string): void {
+    this.displayWidget = false;
+    setTimeout(() => {
+      this.selectedWidgetIndex = index;
+      this.currentWidget = this.configuredWidgets.get(widgetId);
+      this.currentMeasure = this.dataLakeMeasures.get(widgetId);
+      this.currentDashboardItem = this.dashboard.widgets[index] as unknown as DashboardItem;
+      this.currentlyConfiguredWidgetId = widgetId;
+      this.displayWidget = true;
+    });
+  }
+
+  ngAfterViewInit(): void {
+    const obs = new ResizeObserver(entries => {
+      entries.forEach(entry => {
+        const cr = entry.contentRect;
+        this.gridsterItemComponent = {width: cr.width, height: cr.height};
+        this.resizeService.notify({
+          gridsterItem: this.dashboard.widgets[this.selectedWidgetIndex],
+          gridsterItemComponent: this.gridsterItemComponent
+        });
+      });
+    });
+    obs.observe(document.getElementById('slideViewOuter'));
+
+  }
+
+  onWidgetsAvailable(): void {
+    this.selectWidget(0, this.dashboard.widgets[0].id);
+  }
+
+  isGridView(): boolean {
+    return false;
+  }
+
+  selectNewWidget(widgetId): void {
+    this.selectWidget(this.dashboard.widgets.length - 1, widgetId);
+  }
+
+}
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 f6c3d61f5..0d8c40831 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
@@ -16,13 +16,13 @@
   ~
   -->
 
-<div class="h-100 shadow">
+<div class="h-100">
     <div class="box"
          [ngStyle]='{background: configuredWidget.baseAppearanceConfig.backgroundColor,
          color: configuredWidget.baseAppearanceConfig.textColor,
          border: currentlyConfiguredWidgetId === configuredWidget._id ? "2px solid var(--color-accent)" : "2px solid " + configuredWidget.baseAppearanceConfig.backgroundColor}'
          [attr.data-cy]="'widget-' + configuredWidget.baseAppearanceConfig.widgetTitle">
-        <div class="widget-header h-40">
+        <div class="widget-header h-40" *ngIf="!previewMode">
             <div fxFlex="100" fxLayout="row" fxLayoutAlign="start center" class="widget-header-text">
                 {{ configuredWidget.baseAppearanceConfig.widgetTitle }}
             </div>
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 7163672d5..a095f4f22 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
@@ -16,23 +16,15 @@
  *
  */
 
-import {
-  Component,
-  ComponentFactoryResolver,
-  EventEmitter,
-  Input,
-  OnInit,
-  Output,
-  ViewChild
-} from '@angular/core';
+import { Component, ComponentFactoryResolver, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
 import { MatDialog } from '@angular/material/dialog';
 import { GridsterItemComponent } from 'angular-gridster2';
 import {
-  DateRange,
+  DashboardItem,
   DataExplorerWidgetModel,
   DataLakeMeasure,
   DataViewDataExplorerService,
-  DashboardItem,
+  DateRange,
   TimeSettings
 } from '@streampipes/platform-services';
 import { DataDownloadDialog } from '../datadownloadDialog/dataDownload.dialog';
@@ -70,6 +62,12 @@ export class DataExplorerDashboardWidgetComponent implements OnInit {
   @Input()
   currentlyConfiguredWidgetId: string;
 
+  @Input()
+  previewMode = false;
+
+  @Input()
+  gridMode = true;
+
   /**
    * This is the date range (start, end) to view the data and is set in data-explorer.ts
    */
@@ -136,6 +134,8 @@ export class DataExplorerDashboardWidgetComponent implements OnInit {
     componentRef.instance.editMode = this.editMode;
     componentRef.instance.dataViewDashboardItem = this.dashboardItem;
     componentRef.instance.dataExplorerWidget = this.configuredWidget;
+    componentRef.instance.previewMode = this.previewMode;
+    componentRef.instance.gridMode = this.gridMode;
     const removeSub = componentRef.instance.removeWidgetCallback.subscribe(ev => this.removeWidget());
     const timerSub = componentRef.instance.timerCallback.subscribe(ev => this.handleTimer(ev));
 
diff --git a/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts b/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts
index a77a09d41..168228026 100644
--- a/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts
+++ b/ui/src/app/data-explorer/components/widgets/base/base-data-explorer-widget.directive.ts
@@ -20,14 +20,15 @@ import { Directive, EventEmitter, HostBinding, Input, OnDestroy, OnInit, Output
 import { GridsterItem, GridsterItemComponent } from 'angular-gridster2';
 import { WidgetConfigurationService } from '../../../services/widget-configuration.service';
 import {
+  DashboardItem,
   DataExplorerDataConfig,
   DataExplorerField,
-  DataViewQueryGeneratorService,
   DataExplorerWidgetModel,
-  SpQueryResult,
-  DashboardItem,
   DatalakeRestService,
-  TimeSettings } from '@streampipes/platform-services';
+  DataViewQueryGeneratorService,
+  SpQueryResult,
+  TimeSettings
+} from '@streampipes/platform-services';
 import { ResizeService } from '../../../services/resize.service';
 import { FieldProvider } from '../../../models/dataview-dashboard.model';
 import { Observable, Subscription, zip } from 'rxjs';
@@ -52,6 +53,12 @@ export abstract class BaseDataExplorerWidgetDirective<T extends DataExplorerWidg
 
   @Input() timeSettings: TimeSettings;
 
+  @Input()
+  previewMode = false;
+
+  @Input()
+  gridMode = true;
+
   @Input() dataViewDashboardItem: DashboardItem;
   @Input() dataExplorerWidget: T;
 
@@ -80,6 +87,7 @@ export abstract class BaseDataExplorerWidgetDirective<T extends DataExplorerWidg
   }
 
   ngOnInit(): void {
+    const heightOffset = this.gridMode ? 40 : 40;
     this.showData = true;
     const sourceConfigs = this.dataExplorerWidget.dataConfig.sourceConfigs;
     this.fieldProvider = this.fieldService.generateFieldLists(sourceConfigs);
@@ -99,22 +107,26 @@ export abstract class BaseDataExplorerWidgetDirective<T extends DataExplorerWidg
         }
       }
     });
-    this.resizeSub = this.resizeService.resizeSubject.subscribe(info => {
-      if (info.gridsterItem.id === this.dataExplorerWidget._id) {
-        this.onResize(this.gridsterItemComponent.width, this.gridsterItemComponent.height - 40);
-      }
-    });
+    if (!this.previewMode) {
+      this.resizeSub = this.resizeService.resizeSubject.subscribe(info => {
+        if (info.gridsterItem.id === this.dataExplorerWidget._id) {
+          this.onResize(this.gridsterItemComponent.width, this.gridsterItemComponent.height - heightOffset);
+        }
+      });
+    }
     this.timeSelectionSub = this.timeSelectionService.timeSelectionChangeSubject.subscribe(ts => {
       this.timeSettings = ts;
       this.updateData();
     });
     this.updateData();
-    this.onResize(this.gridsterItemComponent.width, this.gridsterItemComponent.height - 40);
+    this.onResize(this.gridsterItemComponent.width, this.gridsterItemComponent.height - heightOffset);
   }
 
   ngOnDestroy(): void {
     this.widgetConfigurationSub.unsubscribe();
-    this.resizeSub.unsubscribe();
+    if (this.resizeSub) {
+      this.resizeSub.unsubscribe();
+    }
     this.timeSelectionSub.unsubscribe();
   }
 
diff --git a/ui/src/app/data-explorer/components/widgets/base/data-explorer-widget-data.ts b/ui/src/app/data-explorer/components/widgets/base/data-explorer-widget-data.ts
index b6927b1bf..4c2d109aa 100644
--- a/ui/src/app/data-explorer/components/widgets/base/data-explorer-widget-data.ts
+++ b/ui/src/app/data-explorer/components/widgets/base/data-explorer-widget-data.ts
@@ -18,7 +18,7 @@
 
 import { EventEmitter } from '@angular/core';
 import { GridsterItem, GridsterItemComponent } from 'angular-gridster2';
-import { DataExplorerWidgetModel, DashboardItem, TimeSettings } from '@streampipes/platform-services';
+import { DashboardItem, DataExplorerWidgetModel, TimeSettings } from '@streampipes/platform-services';
 
 export interface BaseWidgetData<T extends DataExplorerWidgetModel> {
   removeWidgetCallback: EventEmitter<boolean>;
@@ -32,4 +32,6 @@ export interface BaseWidgetData<T extends DataExplorerWidgetModel> {
 
   dataViewDashboardItem: DashboardItem;
   dataExplorerWidget: T;
+  previewMode: boolean;
+  gridMode: boolean;
 }
diff --git a/ui/src/app/data-explorer/components/widgets/time-series-chart/time-series-chart-widget.component.ts b/ui/src/app/data-explorer/components/widgets/time-series-chart/time-series-chart-widget.component.ts
index 9e851b44c..b284fff5c 100644
--- a/ui/src/app/data-explorer/components/widgets/time-series-chart/time-series-chart-widget.component.ts
+++ b/ui/src/app/data-explorer/components/widgets/time-series-chart/time-series-chart-widget.component.ts
@@ -109,15 +109,17 @@ export class TimeSeriesChartWidgetComponent extends BaseDataExplorerWidgetDirect
     }];
 
     super.ngOnInit();
-    this.resizeService.resizeSubject.subscribe(info => {
-      if (info.gridsterItem.id === this.gridsterItem.id) {
-        setTimeout(() => {
-          this.graph.layout.autosize = false;
-          (this.graph.layout as any).width = (info.gridsterItemComponent.width - this.offsetRightLineChart);
-          (this.graph.layout as any).height = (info.gridsterItemComponent.height - 80);
-        }, 100);
-      }
-    });
+    if (!this.previewMode) {
+      this.resizeService.resizeSubject.subscribe(info => {
+        if (info.gridsterItem.id === this.gridsterItem.id) {
+          setTimeout(() => {
+            this.graph.layout.autosize = false;
+            (this.graph.layout as any).width = (info.gridsterItemComponent.width - this.offsetRightLineChart);
+            (this.graph.layout as any).height = (info.gridsterItemComponent.height - 80);
+          }, 100);
+        }
+      });
+    }
   }
 
   transformData(data: SpQueryResult,
diff --git a/ui/src/app/data-explorer/data-explorer.module.ts b/ui/src/app/data-explorer/data-explorer.module.ts
index 369aa8459..f461c17b1 100644
--- a/ui/src/app/data-explorer/data-explorer.module.ts
+++ b/ui/src/app/data-explorer/data-explorer.module.ts
@@ -51,7 +51,7 @@ import {
 import { CoreUiModule } from '../core-ui/core-ui.module';
 import { CustomMaterialModule } from '../CustomMaterial/custom-material.module';
 import { DataDownloadDialog } from './components/datadownloadDialog/dataDownload.dialog';
-import { DataExplorerDashboardGridComponent } from './components/grid/data-explorer-dashboard-grid.component';
+import { DataExplorerDashboardGridComponent } from './components/widget-view/grid-view/data-explorer-dashboard-grid.component';
 import { DataExplorerDashboardOverviewComponent } from './components/overview/data-explorer-dashboard-overview.component';
 import { DataExplorerDashboardPanelComponent } from './components/panel/data-explorer-dashboard-panel.component';
 import { TimeRangeSelectorComponent } from './components/time-selector/timeRangeSelector.component';
@@ -101,6 +101,7 @@ import { NgxEchartsModule } from 'ngx-echarts';
 import { TooMuchDataComponent } from './components/widgets/utils/too-much-data/too-much-data.component';
 import { SpValueHeatmapComponent } from './components/widgets/distribution-chart/value-heatmap/value-heatmap.component';
 import { RouterModule } from "@angular/router";
+import { DataExplorerDashboardSlideViewComponent } from './components/widget-view/slide-view/data-explorer-dashboard-slide-view.component';
 
 export const MY_NATIVE_FORMATS = {
   fullPickerInput: {
@@ -182,6 +183,7 @@ export const MY_NATIVE_FORMATS = {
     DataExplorerDashboardGridComponent,
     DataExplorerDashboardOverviewComponent,
     DataExplorerDashboardPanelComponent,
+    DataExplorerDashboardSlideViewComponent,
     DataExplorerDashboardWidgetComponent,
     DataExplorerDesignerPanelComponent,
     DataExplorerEditDataViewDialogComponent,