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 2021/08/11 09:49:55 UTC

[incubator-streampipes] 02/03: [STREAMPIPES-402] Improve widget management in data explorer

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

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

commit 8e836d6aa5a7525baa0765add4ab3ec6f9d93602
Author: Dominik Riemer <ri...@fzi.de>
AuthorDate: Wed Aug 11 11:39:48 2021 +0200

    [STREAMPIPES-402] Improve widget management in data explorer
---
 .../data-explorer-designer-panel.component.html    | 17 ++++----
 .../data-explorer-designer-panel.component.ts      | 12 ++++--
 .../data-explorer-dashboard-grid.component.html    |  2 +-
 .../data-explorer-dashboard-grid.component.scss    |  6 ++-
 .../grid/data-explorer-dashboard-grid.component.ts | 12 +++---
 ...data-explorer-dashboard-overview.component.html | 14 ++++++-
 .../data-explorer-dashboard-overview.component.ts  | 11 +++---
 .../data-explorer-dashboard-panel.component.html   |  9 +++--
 .../data-explorer-dashboard-panel.component.ts     | 46 +++++++++-------------
 .../data-explorer-dashboard-widget.component.html  | 12 +++---
 .../app/data-explorer/data-explorer.component.html | 36 +++++++++++++----
 .../app/data-explorer/data-explorer.component.ts   | 19 +++++----
 12 files changed, 119 insertions(+), 77 deletions(-)

diff --git a/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.html b/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.html
index 3142c17..cbdee90 100644
--- a/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.html
+++ b/ui/src/app/data-explorer/components/designer-panel/data-explorer-designer-panel.component.html
@@ -16,7 +16,7 @@
   ~
   -->
 
-<div fxFlex="100" fxLayout="column" class="designer-panel-content">
+<div fxFlex="100" fxLayout="column" class="designer-panel-content" *ngIf="currentlyConfiguredWidget">
     <h4 *ngIf="currentlyConfiguredWidget">{{ currentlyConfiguredWidget.baseAppearanceConfig.widgetTitle }}</h4>
     <mat-tab-group [selectedIndex]="selectedIndex" (selectedIndexChange)="selectOptionsPanel($event)" color="accent"
                    class="small">
@@ -26,7 +26,7 @@
     </mat-tab-group>
 
     <div fxFlex="100" fxLayout="column">
-        <div class="designer-panel-config" *ngIf="currentlyConfiguredWidget">
+        <div class="designer-panel-config">
 
             <div *ngIf="selectedIndex == 0">
                 <sp-data-explorer-widget-data-settings [dataLakeMeasure]="dataLakeMeasure" [currentlyConfiguredWidget]="currentlyConfiguredWidget">
@@ -53,10 +53,13 @@
                 </sp-data-explorer-widget-appearance-settings>
             </div>
         </div>
-
-        <div class="designer-panel-config" *ngIf="!currentlyConfiguredWidget" fxFlex="100"
-             fxLayoutAlign="center center" fxLayout="column">
-            <span>Select a widget to open configuration options.</span>
-        </div>
     </div>
 </div>
+<div class="designer-panel-config" *ngIf="!currentlyConfiguredWidget" fxFlex="100"
+     fxLayoutAlign="center center" fxLayout="column">
+    <span class="text-center">Select a widget to open configuration options or add a new widget.</span>
+    <button mat-button color="accent" class="mt-10"
+            (click)="addWidget()">
+        <i class="material-icons">add</i><span>Add widget</span>
+    </button>
+</div>
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 f3b2bd4..7576c62 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
@@ -16,8 +16,8 @@
  *
  */
 
-import {Component, Input, OnInit} from '@angular/core';
-import {DataExplorerWidgetModel, DataLakeMeasure} from "../../../core-model/gen/streampipes-model";
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { DataExplorerWidgetModel, DataLakeMeasure } from '../../../core-model/gen/streampipes-model';
 
 @Component({
   selector: 'sp-data-explorer-designer-panel',
@@ -29,7 +29,9 @@ export class DataExplorerDesignerPanelComponent implements OnInit {
   @Input() currentlyConfiguredWidget: DataExplorerWidgetModel;
   @Input() dataLakeMeasure: DataLakeMeasure;
 
-  selectedIndex: number = 0;
+  @Output() addWidgetEmitter: EventEmitter<void> = new EventEmitter();
+
+  selectedIndex = 0;
 
   ngOnInit(): void {
   }
@@ -38,4 +40,8 @@ export class DataExplorerDesignerPanelComponent implements OnInit {
     this.selectedIndex = index;
   }
 
+  addWidget() {
+    this.addWidgetEmitter.emit();
+  }
+
 }
diff --git a/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.html b/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.html
index a9f3ed3..ee37ae3 100644
--- a/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.html
+++ b/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.html
@@ -22,7 +22,7 @@
 </div>
 <gridster [options]="options" [ngClass]="editMode ? 'edit' : ''" class="custom-gridster-style">
     <ng-container *ngFor="let item of dashboard.widgets;let i=index">
-        <gridster-item [item]="item" #gridsterItemComponent>
+        <gridster-item [item]="item" #gridsterItemComponent class="shadow">
             <sp-data-explorer-dashboard-widget
                     [timeSettings]="timeSettings"
                     (updateCallback)="propagateItemUpdate($event)"
diff --git a/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.scss b/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.scss
index f90e375..0d9fa6b 100644
--- a/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.scss
+++ b/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.scss
@@ -17,7 +17,7 @@
  */
 
 gridster.custom-gridster-style ::ng-deep {
-    background: var(--color-bg-3);
+    background: var(--color-bg-0);
 }
 
 gridster.custom-gridster-style.edit ::ng-deep {
@@ -39,3 +39,7 @@ gridster.scrollVertical ::ng-deep {
     border-left: 1px solid var(--color-bg-1);
     border-right: 1px solid var(--color-bg-1);
 }
+
+.shadow {
+    box-shadow: rgba(50, 50, 93, 0.25) 0px 2px 5px -1px, rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
+}
diff --git a/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.ts b/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.ts
index 31ebb6d..2ff5aa1 100644
--- a/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.ts
+++ b/ui/src/app/data-explorer/components/grid/data-explorer-dashboard-grid.component.ts
@@ -38,8 +38,8 @@ import {
   DataLakeMeasure
 } from '../../../core-model/gen/streampipes-model';
 import { Tuple2 } from '../../../core-model/base/Tuple2';
-import { DatalakeRestService } from "../../../core-services/datalake/datalake-rest.service";
-import { Dashboard, DashboardItem, TimeSettings } from "../../../dashboard/models/dashboard.model";
+import { DatalakeRestService } from '../../../core-services/datalake/datalake-rest.service';
+import { Dashboard, DashboardItem, TimeSettings } from '../../../dashboard/models/dashboard.model';
 
 @Component({
   selector: 'sp-data-explorer-dashboard-grid',
@@ -90,7 +90,7 @@ export class DataExplorerDashboardGridComponent implements OnInit, OnChanges {
       fixedRowHeight: 100,
       fixedColWidth: 100,
       margin: 5,
-      displayGrid: "always",
+      displayGrid: this.editMode ? 'always' : 'none',
       resizable: {enabled: this.editMode},
       itemResizeCallback: ((item, itemComponent) => {
         this.resizeService.notify({
@@ -122,7 +122,7 @@ export class DataExplorerDashboardGridComponent implements OnInit, OnChanges {
       this.configuredWidgets.set(widgetId, response);
       this.dataViewDataExplorerService.getPersistedDataStream(response.pipelineId, response.measureName).subscribe(ps => {
         this.dataLakeMeasures.set(widgetId, ps);
-      })
+      });
     });
   }
 
@@ -149,14 +149,14 @@ export class DataExplorerDashboardGridComponent implements OnInit, OnChanges {
   }
 
   toggleGrid() {
-    this.options.displayGrid = this.options.displayGrid === "none" ? "always" : "none";
+    this.options.displayGrid = this.options.displayGrid === 'none' ? 'always' : 'none';
     this.options.api.optionsChanged();
   }
 
   updateAllWidgets() {
     this.configuredWidgets.forEach((value, key) => {
       this.dataViewDataExplorerService.updateWidget(value).subscribe();
-    })
+    });
   }
 
 }
diff --git a/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.html b/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.html
index 59300fa..ef11d29 100644
--- a/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.html
+++ b/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.html
@@ -55,13 +55,25 @@
                         <td fxFlex="10" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
                             <div fxLayout="row">
                                 <button mat-button mat-icon-button color="accent"
-                                        (click)="showDashboard(element)">
+                                        (click)="showDashboard(element, false)">
                                     <i class="material-icons">visibility</i>
                                 </button>
                             </div>
                         </td>
                     </ng-container>
 
+                    <ng-container matColumnDef="edit">
+                        <th fxFlex="10" fxLayoutAlign="start center" mat-header-cell *matHeaderCellDef> Edit</th>
+                        <td fxFlex="10" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
+                            <div fxLayout="row">
+                                <button mat-button mat-icon-button color="accent"
+                                        (click)="showDashboard(element, true)">
+                                    <i class="material-icons">edit</i>
+                                </button>
+                            </div>
+                        </td>
+                    </ng-container>
+
                     <ng-container matColumnDef="delete">
                         <th fxFlex="10" fxLayoutAlign="start center" mat-header-cell *matHeaderCellDef> Delete</th>
                         <td fxFlex="10" fxLayoutAlign="start center" mat-cell *matCellDef="let element">
diff --git a/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.ts b/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.ts
index 666e9d2..14032c0 100644
--- a/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.ts
+++ b/ui/src/app/data-explorer/components/overview/data-explorer-dashboard-overview.component.ts
@@ -22,6 +22,7 @@ import {MatTableDataSource} from '@angular/material/table';
 import {DataExplorerEditDataViewDialogComponent} from '../../dialogs/edit-dashboard/data-explorer-edit-data-view-dialog.component';
 import {DataViewDataExplorerService} from '../../services/data-view-data-explorer.service';
 import {Dashboard} from "../../../dashboard/models/dashboard.model";
+import { Tuple2 } from '../../../core-model/base/Tuple2';
 
 @Component({
     selector: 'sp-data-explorer-dashboard-overview',
@@ -32,10 +33,10 @@ export class DataExplorerDashboardOverviewComponent implements OnInit {
 
     @Input() dataViewDashboards: Dashboard[];
     @Output() reloadDashboardsEmitter = new EventEmitter<void>();
-    @Output() selectDashboardEmitter = new EventEmitter<Dashboard>();
+    @Output() selectDashboardEmitter = new EventEmitter<Tuple2<Dashboard, boolean>>();
 
     dataSource = new MatTableDataSource<Dashboard>();
-    displayedColumns: string[] = ['name', 'open', 'delete'];
+    displayedColumns: string[] = ['name', 'open', 'edit', 'delete'];
 
     editLabels: boolean;
 
@@ -84,8 +85,8 @@ export class DataExplorerDashboardOverviewComponent implements OnInit {
         });
     }
 
-    showDashboard(dashboard: Dashboard) {
-        this.selectDashboardEmitter.emit(dashboard);
+    showDashboard(dashboard: Dashboard, editMode: boolean) {
+        const dashboardSettings: Tuple2<Dashboard, boolean> = {a: dashboard, b: editMode};
+        this.selectDashboardEmitter.emit(dashboardSettings);
     }
-
 }
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 cd91104..d016b1a 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
@@ -18,19 +18,20 @@
 
 <div fxFlex="100" fxLayout="column">
     <mat-drawer-container class="designer-panel-container h-100 dashboard-grid">
-        <mat-drawer #designerDrawer mode="side" position="end" class="designer-panel">
+        <mat-drawer #designerDrawer [opened]="editMode" mode="side" position="end" class="designer-panel">
             <div fxLayout="column" fxFlex>
                 <div fxLayout="row" class="sp-tab-bg designer-panel-header">
-                    <div fxLayoutAlign="start center" class="designer-panel-title">Configure widget</div>
+                    <div fxLayoutAlign="start center" class="designer-panel-title">Widget Configuration</div>
                     <div fxFlex fxLayoutAlign="end end">
-                        <button mat-button mat-icon-button (click)="closeDrawer()">
-                            <mat-icon>clear</mat-icon>
+                        <button mat-button mat-icon-button (click)="addWidget()">
+                            <mat-icon>add</mat-icon>
                         </button>
                     </div>
                 </div>
                 <sp-data-explorer-designer-panel
                         [currentlyConfiguredWidget]="currentlyConfiguredWidget"
                         [dataLakeMeasure]="dataLakeMeasure"
+                        (addWidgetEmitter)="addWidget()"
                         fxFlex="100">
 
                 </sp-data-explorer-designer-panel>
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 e2c469a..8ea99af 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,17 +16,20 @@
  *
  */
 
-import {Component, EventEmitter, Input, OnInit, Output, ViewChild} from '@angular/core';
-import {MatDialog} from '@angular/material/dialog';
-import {Observable, Subscription} from 'rxjs';
-import {DataExplorerAddVisualizationDialogComponent} from '../../dialogs/add-widget/data-explorer-add-visualization-dialog.component';
-import {DataViewDataExplorerService} from '../../services/data-view-data-explorer.service';
-import {RefreshDashboardService} from '../../services/refresh-dashboard.service';
-import {DataExplorerWidgetModel, DataLakeMeasure} from "../../../core-model/gen/streampipes-model";
-import {DataExplorerDashboardGridComponent} from "../grid/data-explorer-dashboard-grid.component";
-import {MatDrawer} from "@angular/material/sidenav";
-import {Tuple2} from "../../../core-model/base/Tuple2";
-import {Dashboard, DashboardItem, TimeSettings} from "../../../dashboard/models/dashboard.model";
+import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
+import { MatDialog } from '@angular/material/dialog';
+import { Observable, Subscription } from 'rxjs';
+import { DataExplorerAddVisualizationDialogComponent } from '../../dialogs/add-widget/data-explorer-add-visualization-dialog.component';
+import { DataViewDataExplorerService } from '../../services/data-view-data-explorer.service';
+import { RefreshDashboardService } from '../../services/refresh-dashboard.service';
+import {
+  DataExplorerWidgetModel,
+  DataLakeMeasure
+} from '../../../core-model/gen/streampipes-model';
+import { DataExplorerDashboardGridComponent } from '../grid/data-explorer-dashboard-grid.component';
+import { MatDrawer } from '@angular/material/sidenav';
+import { Tuple2 } from '../../../core-model/base/Tuple2';
+import { Dashboard, DashboardItem, TimeSettings } from '../../../dashboard/models/dashboard.model';
 
 @Component({
   selector: 'sp-data-explorer-dashboard-panel',
@@ -35,28 +38,21 @@ import {Dashboard, DashboardItem, TimeSettings} from "../../../dashboard/models/
 })
 export class DataExplorerDashboardPanelComponent implements OnInit {
 
-  @Input()
-  dashboard: Dashboard;
+  @Input() dashboard: Dashboard;
 
   /**
    * This is the date range (start, end) to view the data and is set in data-explorer.ts
    */
-  @Input()
-  timeSettings: TimeSettings;
+  @Input() timeSettings: TimeSettings;
+  @Input() editMode: boolean;
 
-  @Input('editMode')
-  editMode: boolean;
-
-  @Output('editModeChange')
-  editModeChange: EventEmitter<boolean> = new EventEmitter();
+  @Output() editModeChange: EventEmitter<boolean> = new EventEmitter();
 
   @ViewChild('dashboardGrid') dashboardGrid: DataExplorerDashboardGridComponent;
   @ViewChild('designerDrawer') designerDrawer: MatDrawer;
 
   public items: Dashboard[];
 
-  protected subscription: Subscription;
-
   widgetIdsToRemove: string[] = [];
   widgetsToUpdate: Map<string, DataExplorerWidgetModel> = new Map<string, DataExplorerWidgetModel>();
 
@@ -155,15 +151,9 @@ export class DataExplorerDashboardPanelComponent implements OnInit {
     this.dashboardGrid.toggleGrid();
   }
 
-  closeDrawer() {
-    this.designerDrawer.close();
-    this.dashboardGrid.options.api.optionsChanged();
-  }
-
   updateCurrentlyConfiguredWidget(currentWidget: Tuple2<DataExplorerWidgetModel, DataLakeMeasure>) {
     this.widgetsToUpdate.set(currentWidget.a._id, currentWidget.a);
     this.currentlyConfiguredWidget = currentWidget.a;
     this.dataLakeMeasure = currentWidget.b;
-    this.designerDrawer.open();
   }
 }
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 d959dc8..09d98ab 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,18 +16,18 @@
   ~
   -->
 
-<div class="h-100">
+<div class="h-100 shadow">
     <div class="box" [ngStyle]="{background: configuredWidget.baseAppearanceConfig.backgroundColor, color: configuredWidget.baseAppearanceConfig.textColor}">
         <div class="widget-header">
-        <div class="m-0 row header h-40" *ngIf="editMode">
+        <div class="m-0 row header h-40">
             <div fxFlex="100" fxLayout="row" fxLayoutAlign="start center" class="widget-header-text">
                 {{ configuredWidget.baseAppearanceConfig.widgetTitle }}
             </div>
-            <div fxFlex="100" fxLayout="row" fxLayoutAlign="end center" *ngIf="editMode">
-                <button mat-icon-button (click)="triggerWidgetEditMode()">
+            <div fxFlex="100" fxLayout="row" fxLayoutAlign="end center">
+                <button mat-icon-button (click)="triggerWidgetEditMode()" *ngIf="editMode">
                     <mat-icon>edit</mat-icon>
                 </button>
-                <button mat-icon-button [matMenuTriggerFor]="menu" aria-label="Example icon-button with a menu">
+                <button mat-icon-button [matMenuTriggerFor]="menu" aria-label="More options">
                     <mat-icon>more_vert</mat-icon>
                 </button>
                 <mat-menu #menu="matMenu">
@@ -35,7 +35,7 @@
                         <mat-icon>get_app</mat-icon>
                         <span>Download data</span>
                     </button>
-                    <button mat-menu-item (click)="removeWidget()">
+                    <button mat-menu-item (click)="removeWidget()" *ngIf="editMode">
                         <mat-icon>clear</mat-icon>
                         <span>Delete widget</span>
                     </button>
diff --git a/ui/src/app/data-explorer/data-explorer.component.html b/ui/src/app/data-explorer/data-explorer.component.html
index ea055bf..c302fde 100644
--- a/ui/src/app/data-explorer/data-explorer.component.html
+++ b/ui/src/app/data-explorer/data-explorer.component.html
@@ -26,20 +26,42 @@
                         <mat-tab *ngFor="let dataViewDashboard of dataViewDashboards" label="{{dataViewDashboard.name}}"></mat-tab>
                     </mat-tab-group>
                 </div>
+                <div fxFlex fxLayoutAlign="end center" *ngIf="selectedIndex > 0">
+                    <button mat-icon-button [matMenuTriggerFor]="menu" aria-label="Options">
+                        <mat-icon>more_vert</mat-icon>
+                    </button>
+                    <mat-menu #menu="matMenu">
+                        <button mat-menu-item (click)="editMode = true" *ngIf="!editMode">
+                            <mat-icon>edit</mat-icon>
+                            <span>Edit dashboard</span>
+                        </button>
+                        <button mat-menu-item (click)="getDashboards(selectedDataViewDashboard._id)">
+                            <mat-icon>refresh</mat-icon>
+                            <span>Reload 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>
+                            <mat-icon>clear</mat-icon>
+                            <span>Delete dashboard</span>
+                        </button>
+                    </mat-menu>
+                </div>
             </div>
         </div>
     </div>
-    <div class="fixed-height data-explorer-options sp-tab-bg" fxLayout="row" *ngIf="selectedIndex > 0">
-        <div class="data-explorer-options-item pl-10" fxLayoutAlign="start center" fxLayout="row">
+    <div class="fixed-height data-explorer-options sp-tab-bg page-container-nav" fxLayout="row" *ngIf="selectedIndex > 0 && (editMode || timeRangeVisible)">
+        <div class="data-explorer-options-item pl-10" fxLayoutAlign="start center" fxLayout="row" *ngIf="editMode">
             <button mat-button mat-raised-button color="accent" matTooltip="Save" [matTooltipPosition]="'above'" (click)="saveDashboard()">
                 <mat-icon>save</mat-icon>&nbsp;<span>Save</span>
             </button>
         </div>
-        <div class="data-explorer-options-item" fxLayoutAlign="start center" fxLayout="row">
-            <button mat-button mat-raised-button color="accent" matTooltip="Add visualization" [matTooltipPosition]="'above'" (click)="addVisualization()">
-                <mat-icon>add</mat-icon>&nbsp;<span>Add visualization</span>
-            </button>
-        </div>
         <div class="data-explorer-options-item" fxLayoutAlign="end center" fxFlex fxLayout="row">
             <sp-time-range-selector *ngIf="selectedIndex" (dateRangeEmitter)="updateDateRange($event)" [dateRange]="selectedDataViewDashboard.dashboardTimeSettings"></sp-time-range-selector>
         </div>
diff --git a/ui/src/app/data-explorer/data-explorer.component.ts b/ui/src/app/data-explorer/data-explorer.component.ts
index 3600769..37a79e8 100644
--- a/ui/src/app/data-explorer/data-explorer.component.ts
+++ b/ui/src/app/data-explorer/data-explorer.component.ts
@@ -16,11 +16,12 @@
  *
  */
 
-import {Component, OnInit, ViewChild} from '@angular/core';
-import {DataViewDataExplorerService} from './services/data-view-data-explorer.service';
-import {RefreshDashboardService} from './services/refresh-dashboard.service';
-import {DataExplorerDashboardPanelComponent} from "./components/panel/data-explorer-dashboard-panel.component";
-import {Dashboard, TimeSettings} from "../dashboard/models/dashboard.model";
+import { Component, OnInit, ViewChild } from '@angular/core';
+import { DataViewDataExplorerService } from './services/data-view-data-explorer.service';
+import { RefreshDashboardService } from './services/refresh-dashboard.service';
+import { DataExplorerDashboardPanelComponent } from './components/panel/data-explorer-dashboard-panel.component';
+import { Dashboard, TimeSettings } from '../dashboard/models/dashboard.model';
+import { Tuple2 } from '../core-model/base/Tuple2';
 
 @Component({
   selector: 'sp-data-explorer',
@@ -33,9 +34,10 @@ export class DataExplorerComponent implements OnInit {
   selectedIndex = 0;
   dashboardsLoaded = false;
   dashboardTabSelected = false;
+  timeRangeVisible = true;
 
   editMode = true;
-  gridVisible: boolean = true;
+  gridVisible = true;
 
   dataViewDashboards: Dashboard[];
 
@@ -54,8 +56,9 @@ export class DataExplorerComponent implements OnInit {
 
   }
 
-  openDashboard(dashboard: Dashboard) {
-    const index = this.dataViewDashboards.indexOf(dashboard);
+  openDashboard(dashboard: Tuple2<Dashboard, boolean>) {
+    this.editMode = dashboard.b;
+    const index = this.dataViewDashboards.indexOf(dashboard.a);
     this.selectDashboard((index + 1));
   }