You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by mb...@apache.org on 2018/08/15 02:27:30 UTC

[04/11] asterixdb git commit: [NO ISSUE] Asterixdb-dashboard baseline:

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3e5815a7/asterixdb/asterix-dashboard/src/node/src/app/dashboard/metadata/metadata-container.component.ts
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/metadata/metadata-container.component.ts b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/metadata/metadata-container.component.ts
deleted file mode 100755
index c8382cf..0000000
--- a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/metadata/metadata-container.component.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-import { Component, ViewChild } from '@angular/core';
-
-@Component({
-	moduleId: module.id,
-	selector: 'awc-metadata-container',
-	templateUrl: 'metadata-container.component.html',
-	styleUrls: ['metadata-container.component.scss']
-})
-
-export class MetadataContainerComponent {
-
-	@ViewChild('dataverses') dataverses ;
-	@ViewChild('datasets') datasets ;
-	@ViewChild('datatypes') datatypes ;
-	@ViewChild('indexes') indexes ;
-	message = "";
-
-	constructor() {}
-
-	tabChange() {
-		this.indexes.cleanUp();
-		this.datasets.cleanUp();
-		this.datatypes.cleanUp();
-		this.dataverses.cleanUp();
-	}
-
-	
-}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3e5815a7/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/codemirror.component.scss
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/codemirror.component.scss b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/codemirror.component.scss
deleted file mode 100755
index ba795c2..0000000
--- a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/codemirror.component.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
-Licensed 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.
-*/
-/* -- Place holder for future expansion --> */
-code {
-	width: 100%;
-	height: 100%;
-	padding: 10%;
-    margin: 0; 
-    overflow-wrap: break-word;
-    word-break: break-all;
-    background-color: pink;
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3e5815a7/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/codemirror.component.ts
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/codemirror.component.ts b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/codemirror.component.ts
deleted file mode 100755
index 91b711d..0000000
--- a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/codemirror.component.ts
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
-Licensed 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.
-*/
-/**
- * Integrating codemirror (using ng2-codemirror) with our application
- *
- * component from "https://runkit.com/npm/ng2-codemirror"
- *                "https://www.npmjs.com/package/ng2-codemirror"
- * copy component from /src/codemirror.component.ts
- * and modified for custom mode (asterix aql, sql++ code hilighting)
- *
- * therefore, actually we don't need to "npm install ng2-codemirror"
- *
- * Because on the outside of this component,
- * It was hard to access the codemirror instance that 'ng-codemirror' use
- * So, we copied the component in our application and modified it
- *
- * 'codemirror.js(^5.23.0)' is included in the 'index.html'
- * And in this component(codemirror.component.ts)
- * add statement like "declare var CodeMirror: any;"
- *
- * I don't know whether this is right way
- *
- * ref 1) usage : https://embed.plnkr.co/8e9gxss9u10VeFrv29Zt/
- * ref 2) custom mode : http://jsfiddle.net/TcqAf/99/
- * ref 3) integrating : http://stackoverflow.com/questions/37092142/integrating-codemirror-with-angular2-typescript
- * ref 3) integrating :  https://medium.com/@s_eschweiler/using-external-libraries-with-angular-2-87e06db8e5d1#.8ok74uvwg
- */
- import {
-   Component,
-   Input,
-   Output,
-   ElementRef,
-   ViewChild,
-   EventEmitter,
-   forwardRef,
-   AfterViewInit,
-   OnDestroy
- } from '@angular/core';
- import { NG_VALUE_ACCESSOR } from '@angular/forms';
- import * as CodeMirror from 'codemirror';
-
-/**
- * CodeMirror component
- * Usage :
- * <codemirror [(ngModel)]="data" [config]="{...}"></codemirror>
- */
-@Component({
-  moduleId: module.id,
-  selector: 'codemirror',
-  providers: [
-    {
-      provide: NG_VALUE_ACCESSOR,
-      useExisting: forwardRef(() => CodemirrorComponent),
-      multi: true
-    }
-  ],
-  styleUrls: ['codemirror.component.scss'],
-  template: `<textarea class="code" #host></textarea>`,//,
-})
-
-export class CodemirrorComponent implements AfterViewInit, OnDestroy {
-  @Input() config;
-  @Output() change = new EventEmitter();
-  @Output() focus = new EventEmitter();
-  @Output() blur = new EventEmitter();
-  @Output() instance = null;
-  @ViewChild('host') host;
-  _value = '';
-
-  /**
-   * Constructor
-   */
-  constructor(){
-		/**
-		 * Custom mode for AsterixDB
-		 */
-		CodeMirror.defineMode("asterix", function(){
-		  var KEYWORD_MATCH = [
-				// AQL
-				"drop", "dataverse", "dataset",
-				"if", "exists", "create",
-				"use", "type", "as", "closed",
-				"primary", "key",  "hints", "cardinality",
-				"index", "on", "btree", "rtree", "keyword",
-				"for", "in", "Metadata", "Dataset",
-				"return", "Index", "load", "using", "localfs", "path", "format",
-				// Query (not perfect)
-				"from", "in", "with", "group", "by", "select",
-				"let", "where", "order", "asc", "desc", "limit",
-				"keeping", "offset", "distinct", "or", "and",
-				// Built in functions (TODO)
-				// Built in functions (TODO)
-				// Built in functions (TODO)
-				// Asterix Data Model
-				// Primitive type
-				"boolean",
-				"tinyint", "smallint", "integer", "bigint",
-				"float", "double",
-				"string",
-				"binary", "hex", "base64",
-				"point", "line", "rectangle", "circle", "polygon",
-				"date", "time", "datetime", "duration", "interval", "uuid",
-				// Incomplete information type
-				"null", "missing",
-				// Derived type
-				// object {}, array [], multiset {{}}
-				// SQL++
-				"DROP", "DATAVERSE", "IF", "EXISTS", "CREATE", "USE", "TYPE", "AS", "DATASET", "PRIMARY", "KEY",
-				"INDEX", "SELECT", "VALUE", "INSERT", "INTO", "FROM", "WHERE", "AND", "SOME", "IN", "SATISFIES", "IS", "UNKNOWN", "NOT", "EVERY",
-				"GROUP", "BY", "ORDER", "DESC", "LIMIT", "OR", "SET", "DELETE", "LOAD", "USING",
-			];
-
-			//"(", ")","{{", "}}", "[", "]",	"{", "}",  ";", ",", ":","?", "=",
-      var VAR_MATCH = /[$][a-zA-Z]+(\d*)/;
-			var DOT_MATCH = /[.](\S)*/;
-			var DOUBLE_QUOTE_MATCH = /["].*["]/;
-			var SINGLE_QUOTE_MATCH = /['].*[']/;
-			var BREAK_POINT = /(\s)/;
-
-			return {
-				startState: function() {return {inString: false};},
-				token: function(stream, state) {
-					if (state.newLine == undefined)state.newLine = true;
-
-					//match variable reference
-					if (stream.match(VAR_MATCH)) {
-						return "variable";
-					}
-
-					if (stream.match(DOT_MATCH)) {
-						return "dot-variable";
-					}
-
-					//string variable match
-					if (stream.match(DOUBLE_QUOTE_MATCH)) {
-						return "string";
-					}
-					if (stream.match(SINGLE_QUOTE_MATCH)) {
-						return "string";
-					}
-
-					//keyword match
-					for (var i in KEYWORD_MATCH){
-						if (state.newLine && stream.match(KEYWORD_MATCH[i])){
-								return "keyword";
-						 }
-					}
-
-					if (stream.peek() === " " || stream.peek() === null){
-						state.newLine = true;
-					}else{
-						state.newLine = false;
-					}
-					stream.next();
-					return null;
-				}
-			};
-		});
-	}
-
-  get value() { return this._value; };
-
-  @Input() set value(v) {
-    if (v !== this._value) {
-      this._value = v;
-      this.onChange(v);
-    }
-  }
-
-  /**
-   * On component destroy
-   */
-  ngOnDestroy() {}
-
-  /**
-   * On component view init
-   */
-  ngAfterViewInit() {
-    this.config = this.config || {};
-    this.codemirrorInit(this.config);
-  }
-
-  /**
-   * Initialize codemirror
-   */
-  codemirrorInit(config){
-    this.instance = CodeMirror.fromTextArea(this.host.nativeElement, config);
-    this.instance.setValue(this._value);
-    this.instance.setSize(null, 90);
-    this.instance.on('change', () => {
-      this.updateValue(this.instance.getValue());
-    });
-
-    this.instance.on('focus', () => {
-      this.focus.emit();
-    });
-
-    this.instance.on('blur', () => {
-      this.blur.emit();
-    });
-  }
-
-  /**
-   * Value update process
-   */
-  updateValue(value){
-    this.value = value;
-    this.onTouched();
-    this.change.emit(value);
-  }
-
-  /**
-   * Implements ControlValueAccessor
-   */
-  writeValue(value){
-    this._value = value || '';
-    if (this.instance) {
-      this.instance.setValue(this._value);
-    }
-  }
-
-  onChange(_) {}
-  onTouched() {}
-  registerOnChange(fn){this.onChange = fn;}
-  registerOnTouched(fn){this.onTouched = fn;}
-}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3e5815a7/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.html
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.html b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.html
index 2eec6b7..86e9927 100755
--- a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.html
+++ b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.html
@@ -10,19 +10,48 @@ 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.
-*/ -->
-<mat-card class="input-card">
-	 <mat-toolbar color="primary" class="input-selector">
-			<mat-icon class="toolbar-icon">menu</mat-icon>
-			<span>INPUT: SQL++</span>	
-			<span class="spacer"></span>
-	</mat-toolbar>
-	<mat-card-content class="content-area">
-		<div class="codemirror-container">
-			<codemirror class="code" #host [(ngModel)]="queryString" [config]="codemirrorConfig"></codemirror>
-		</div>
-	</mat-card-content>
-	<mat-card-actions class="actions">
-		<button mat-button class="query-button" (click)="onClick()">RUN</button>
-	</mat-card-actions>
-</mat-card>
+*/-->
+<mat-expansion-panel class="card" hideToggle [expanded]="true">
+    <mat-expansion-panel-header class="header" >
+        <mat-panel-title>
+            <mat-panel-title>SQL++ INPUT ({{currentQuery+1}}/{{preparedQueryCount}})
+            </mat-panel-title>
+            <mat-panel-description></mat-panel-description>
+            <mat-spinner *ngIf="querySpinnerVisible" [color]="blue" [diameter]="15" class="spinner"></mat-spinner>
+        </mat-panel-title>
+    </mat-expansion-panel-header>
+    <mat-panel-description class="content-area">
+        <div class='dataverses'>
+            <div>SELECT DATAVERSE:</div>
+            <mat-form-field>
+                <mat-select [(ngModel)]="selected" (selectionChange)="dataverseSelected()">
+                <!-- <mat-option [value]='none'>None</mat-option> -->
+                <mat-option *ngFor="let dataverse of dataverses" [value]="dataverse.DataverseName">
+                    {{dataverse.DataverseName}}
+                </mat-option>
+                </mat-select>
+            </mat-form-field>
+        </div>
+        <div class="codemirror-container">
+            <textarea class="code" #editor></textarea>
+        </div>
+        <div class="history">
+            <div>HISTORY ({{viewCurrentHistory}}/{{history.length}})</div>
+            <button mat-button class='input-button' (click)="onClickNextHistory()" matTooltip="History: Next"><mat-icon>keyboard_arrow_up</mat-icon></button>
+            <button mat-button class='input-button' (click)="onClickPrevHistory()" matTooltip="History: Prev"><mat-icon>keyboard_arrow_down</mat-icon></button>
+        </div>
+    </mat-panel-description>
+    <mat-action-row>
+        <div class="message">
+            <span *ngIf="querySuccess" class="metrics">{{metricsString}}</span>
+            <span *ngIf="queryError" class="queryErrorMessage">{{queryErrorMessageString}}</span>
+        </div>
+        <div class="space"></div>
+        <button mat-button class='input-button' (click)="onClickNew()" matTooltip="New Query Input">NEW INPUT</button>
+        <button mat-button class='input-button' (click)="onClickClear()" matTooltip="Clear Query Input">CLEAR</button>
+        <button mat-button class='input-button run' (click)="onClickRun()" matTooltip="Execute Query Input">RUN</button>
+        <button mat-button class='input-button' (click)="onClickPrevious()" [disabled]="checkPrevious()" matTooltip="Previous Query Input">PREVIOUS</button>
+        <button mat-button class='input-button' (click)="onClickNext()" [disabled]="checkNext()" matTooltip="Next Query Input">NEXT</button>
+        <button mat-button class='input-button' (click)="onClickMetadata()" [disabled]="" matTooltip="Next Query Input">METADATA</button>
+    </mat-action-row>
+</mat-expansion-panel>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3e5815a7/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.scss
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.scss b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.scss
index 437ff58..04b4eb3 100755
--- a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.scss
+++ b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.scss
@@ -11,72 +11,91 @@ 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.
 */
-$query-spacing-unit: 5px;
 
-.input-card {
-	display: flex;
-	flex-flow: column;
-	padding: 0;
-	margin: ($query-spacing-unit * 2);
-	height: 200px;
-	width: 100%;
-	min-height: 150px; 
+$query-spacing-unit: 5px;
 
-	//background-color: orange;
-}
-  
-.toolbar-icon {
-	padding: 0 14px 0 0;	
-	margin: 0;
+.card {
+    display: block;
+    margin: 0 0px 0 0px;
+    padding: 0;
+    margin: ($query-spacing-unit);
+    border-radius: 4px;
 }
 
-.spacer {
-	flex: 1 1 auto;
+
+.spinner {
+    margin-left: 15px;
+    &::ng-deep circle {
+        stroke: blue;
+    }
 }
-  
-.input-selector {
-	max-height: 42px;
-	min-height: 42px;
-	justify-content: center;
-	//align-items: center;
-	font-size: 0.80rem;
-	font-weight: 500;
-	background-color: white;
-	border: 1px solid rgba(54, 147, 209, 0.87);
+
+.header {
+    max-height: 42px;
+    min-height: 42px;
+    font-size: 0.80rem;
+    font-weight: 500;
+    border-bottom: 1px solid gray;
 }
 
 .content-area {
-	//position: relative;
-	color: hsla(0,0%,0%,.87);
-	//height: 102px;
-	padding: 0;
-	margin: 0;
-	overflow: none;
-  }
+    //min-height: 130px;
+}
 
 .codemirror-container {
-	width: 95%;
-	height: 98%;
-	padding: 0; // ($query-spacing-unit * 2);
-	margin: 0 auto;
-	font-size: 14px;
-	//letter-spacing: 3px;
-	line-height: 1.8;
-	background-color: red;
+    width: 100%;
+    min-height: 98%;
+    padding: 0;
+    margin: 0 auto;
+    margin-top: 15px;
+    line-height: 1.8;
+    border: 1px dashed gainsboro;
+}
+
+.input-button {
+    font-size: 12px !important;
+}
+
+.metrics {
+    color: blue;
+    font-size: 14px !important;
+    font-size: 1.0rem;
+    font-weight: 500;
+    margin: 0;
+    padding: 0;
+}
+
+.space {
+    flex: 1 1 20%
+}
+
+.queryErrorMessage {
+    color: rgba(209, 54, 54, 0.87);
+    word-break: break-all;
+    font-size: 1.0rem;
+    font-weight: 500;
+    margin: 0;
+    padding: 0;
+}
+
+.run {
+    color: blue;
+}
+
+.dataverses {
+    margin-top: 15px;
+    margin-right: 15px;
+    font-size: 0.80rem !important;
+    font-weight: 500 !important;
 }
 
-//.code {
-//	width: 100%;
-//	height: 100%;
-//	padding: 0;
-//	margin: 0; 
-//	overflow-wrap: break-word;
-//	word-break: break-all;
-//}
-
-.actions {
-	border-top: 1px solid rgba(0, 0, 0, 0.1);
-	color: rgba(54, 147, 209, 0.87);
-	padding-left: $query-spacing-unit;
-	margin: 0;
+.history {
+    display: flex;
+    flex-flow: column;
+    align-items: center;
+    width: 88px;
+    margin-top: 15px;
+    margin-left: 15px;
+    font-size: 0.80rem !important;
+    font-weight: 500 !important;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3e5815a7/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.ts
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.ts b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.ts
index 9be9bd9..d17c28a 100755
--- a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.ts
+++ b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/input.component.ts
@@ -12,79 +12,361 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 import { Component, ViewChild } from '@angular/core';
-import { Observable } from 'rxjs/Observable';
+import { Observable } from 'rxjs';
 import { Store } from '@ngrx/store';
-import * as sqlQueryActions from '../../shared/actions/query.actions'
+import * as sqlQueryActions from '../../shared/actions/query.actions';
+import * as appActions from '../../shared/actions/app.actions'
+import * as dataverseActions from '../../shared/actions/dataverse.actions'
 import * as CodeMirror from 'codemirror';
-
 /*
- * query component
- * has editor (codemirror) for writing some query
+ * Query component
+ * has editor (codemirror)
  */
 @Component({
-	moduleId: module.id,
-	selector: 'awc-query',
-	templateUrl:'input.component.html',
-	styleUrls: ['input.component.scss']
+    moduleId: module.id,
+    selector: 'awc-query',
+    templateUrl: 'input.component.html',
+    styleUrls: ['input.component.scss']
 })
 
 export class InputQueryComponent {
-	private guideSelectedDataset$: Observable<any>;		
-	private dataverses$: Observable<any>;	
-	private datatypes$: Observable<any>;
-	private datasets$: Observable<any>;	
-	private indexes$: Observable<any>;	
-	dataverses = [];
-	datatypes = [];
-	datasets = [];
-	indexes = [];
-	datasetName = "";
-	dataverseName = "";
-	queryString: string = ""
-	
-	/* Codemirror configuration
-	*/
-	codemirrorConfig = 	{ 	mode: "asterix",
-							lineWrapping: true,
-							showCursorWhenSelecting: true,
-							autofocus: true
-						}	;
-
-	loaded$: Observable<any>
-
-	constructor(private store: Store<any>) {
-		// Watching for guide selected or clicked dataset
-		this.guideSelectedDataset$ = this.store.select(s => s.dataset.guideSelectsDataset);
-		this.guideSelectedDataset$.subscribe((data: any) => {
-			if (data) {
-				this.datasetName = data;
-				for (let i = 0; i < this.datasets.length; i++) {
-					if ( this.datasets[i]['DatasetName'] === this.datasetName ) {
-						this.dataverseName = this.datasets[i]['DataverseName'];
-					}
-				}
-				this.queryString = "USE " + this.dataverseName + "; SELECT * FROM " + this.datasetName;
-			}
-		});
-
-		// Watching for Datatypes
-		this.dataverses$ = this.store.select(s => s.dataverse.dataverses.results);
-		this.dataverses$.subscribe((data: any[]) => {
-			this.dataverses = data;
-		});
-
-		// Watching for Datasets
-		this.datasets$ = this.store.select(s => s.dataset.datasets.results);
-		this.datasets$.subscribe((data: any[]) => {
-			this.datasets = data;
-		});
-	}
-
-	getQueryResults(queryString: string) {
-    	this.store.dispatch(new sqlQueryActions.ExecuteQuery(queryString));
-  	}
-
-	onClick() {
-		this.getQueryResults(this.queryString.replace(/\n/g, " "));
-	}
+    currentQuery = 0;
+    queryString: string = "";
+    metricsString: {};
+    queryErrorMessageString: string = "";
+    collapse = false;
+    input_expanded_icon = 'expand_less';
+    queryRequest: any;
+    queryPrepare: any;
+    queryMetrics$: Observable <any> ;
+    queryMetrics: {};
+    querySuccess$: Observable <any> ;
+    querySuccess: Boolean = false;
+    queryError$: Observable <any> ;
+    queryError: Boolean = false;
+    queryErrorMessage$: Observable <any> ;
+    queryErrorMessages: {};
+    queryPrepared$: Observable <any> ;
+    queryPrepared: {};
+    preparedQueryCount: number;
+    previousDisabled = true;
+    nextDisabled = true;
+    querySuccesResults: any;
+    querySpinnerVisible: boolean = false;
+    dataverses$: Observable<any>;
+    dataverses: any;
+    defaultDataverse = 'Default';
+    selected = 'Default';
+    history = [];
+    currentHistory = 0;
+    viewCurrentHistory = 0; // for the view
+    sideMenuVisible$: Observable<any>;
+    sideMenuVisible: any;
+    none = 'None';
+    /* Codemirror configuration */
+    codemirrorConfig = {
+    mode: "asterix",
+    lineWrapping: true,
+    showCursorWhenSelecting: true,
+    autofocus: true,
+    lineNumbers: true,
+    };
+
+    constructor(private store: Store < any > ) {
+        this.currentQuery = 0;
+        this.querySuccess$ = this.store.select(s => s.sqlQuery.successHash);
+        this.querySuccess$.subscribe((data: any) => {
+            this.querySuccesResults = data;
+            this.querySpinnerVisible = false;
+            if (data != undefined && data[this.currentQuery] === true) {
+                this.querySuccess = true;
+            } else {
+                this.querySuccess = false;
+            }
+        })
+
+        /* Watching for SQL Input Errors in current Query */
+        this.queryError$ = this.store.select(s => s.sqlQuery.errorHash);
+        this.queryError$.subscribe((data: any) => {
+            this.querySpinnerVisible = false;
+            if (data != undefined && data[this.currentQuery] === true) {
+                this.queryError = true;
+                this.showErrors();
+            } else {
+                this.queryError = false;
+            }
+        })
+
+        /* Watching for Queries that are in prepared state,
+        * those are SQL strings that still has not been executed
+        */
+        this.queryPrepared$ = this.store.select(s => s.sqlQuery.sqlQueryPrepared);
+        this.queryPrepared$.subscribe((data: any) => {
+            if (data) {
+                this.queryPrepared = data
+                this.preparedQueryCount = Object.keys(this.queryPrepared).length;
+                if (this.preparedQueryCount == 0) {
+                    // Initialize Query Editor, prepare the default query
+                    this.queryPrepare = {
+                        editorId: String(this.currentQuery),
+                        queryString: this.queryString
+                    };
+                    this.store.dispatch(new sqlQueryActions.PrepareQuery(this.queryPrepare));
+                } else {
+                    if (this.queryPrepared && this.queryPrepared[this.currentQuery]) {
+                        this.queryString = this.queryPrepared[this.currentQuery];
+                    }
+                }
+            } else {
+                this.queryPrepared = {};
+            }
+        })
+
+        /* Watching for Metrics */
+        this.queryMetrics$ = this.store.select(s => s.sqlQuery.sqlQueryMetrics);
+        this.queryMetrics$.subscribe((data: any) => {
+            if (data != undefined) {
+                this.queryMetrics = Object.assign(data);
+                if (this.queryMetrics && this.queryMetrics[this.currentQuery]) {
+                    this.metricsString = "SUCCESS: ";
+                    this.metricsString += " Execution time: " + this.queryMetrics[this.currentQuery].executionTime;
+                    this.metricsString += " Elapsed time: " + this.queryMetrics[this.currentQuery].elapsedTime;
+                }
+            } else {
+                this.queryMetrics = {};
+            }
+        })
+
+        /* Watching for SQL Input Errors: Error Message stored in Query Cache */
+        this.queryErrorMessage$ = this.store.select(s => s.sqlQuery.sqlQueryErrorHash);
+        this.queryErrorMessage$.subscribe((data: any) => {
+            if (data) {
+                this.queryErrorMessages = data;
+                this.showErrors();
+            } else {
+                this.queryErrorMessages = {};
+            }
+        })
+
+        this.preparedQueryCount = 0;
+        // Initialize Query Editor, prepare the default query
+        this.queryPrepare = {
+            editorId: String(this.currentQuery),
+            queryString: this.queryString
+        };
+        this.store.dispatch(new sqlQueryActions.PrepareQuery(this.queryPrepare));
+        // lets inform other views what's the current SQL editor
+        this.store.dispatch(new appActions.setEditorIndex(String(this.currentQuery)));
+    }
+
+    ngOnInit() {
+        this.dataverses$ = this.store.select(s => s.dataverse.dataverses.results);
+        // Watching for Dataverses
+        this.dataverses$ = this.store.select(s => s.dataverse.dataverses.results);
+        this.dataverses$.subscribe((data: any[]) => {
+            this.dataverses = data;
+            this.defaultDataverse = 'KAMON'
+        });
+        this.store.dispatch(new dataverseActions.SelectDataverses('-'));
+    }
+
+    showMetrics() {
+        this.querySuccess = false;
+        if (this.queryMetrics && this.queryMetrics[this.currentQuery] && this.querySuccesResults[this.currentQuery]) {
+            this.metricsString = "SUCCESS: ";
+            this.metricsString += " Execution time: " + this.queryMetrics[this.currentQuery].executionTime;
+            this.metricsString += " Elapsed time: " + this.queryMetrics[this.currentQuery].elapsedTime;
+            this.querySuccess = true;
+        }
+    }
+
+    showErrors() {
+        this.queryError = false;
+        if (this.queryErrorMessages && this.queryErrorMessages[this.currentQuery]) {
+            let errorObject = this.queryErrorMessages[this.currentQuery];
+            if (errorObject.length != 0) {
+            this.queryErrorMessageString = "ERROR: Code: " + JSON.stringify(errorObject[0].code, null, 8);
+            this.queryErrorMessageString += " " + JSON.stringify(errorObject[0].msg, null, 8);
+            this.queryError = true;
+            }
+        }
+    }
+
+    getQueryResults(queryString: string) {
+        let QueryOrder = this.currentQuery;
+        this.queryRequest = {
+            requestId: String(QueryOrder),
+            queryString: queryString
+        };
+        this.store.dispatch(new sqlQueryActions.ExecuteQuery(this.queryRequest));
+        this.querySpinnerVisible = true;
+    }
+
+    onClickRun() {
+        this.getQueryResults(this.queryString); // .replace(/\n/g, " "));
+        this.history.push(this.queryString);
+        this.currentHistory = this.history.length - 1;
+        this.viewCurrentHistory = this.history.length;
+    }
+
+    onClickNew() {
+        // Saving first
+        this.queryPrepare = {
+            editorId: String(this.currentQuery),
+            queryString: this.queryString
+        };
+        this.store.dispatch(new sqlQueryActions.PrepareQuery(this.queryPrepare));
+        // Prepare a new Query String, cleanup screen messages
+        this.currentQuery = Object.keys(this.queryPrepared).length;
+        this.queryString = "";
+        this.editor.getDoc().setValue(this.queryString);
+        this.queryErrorMessageString = "";
+        this.metricsString = "";
+        this.querySuccess = false;
+        this.queryError = false;
+        this.queryPrepare = {
+            editorId: String(this.currentQuery),
+            queryString: ""
+        };
+        this.store.dispatch(new sqlQueryActions.PrepareQuery(this.queryPrepare));
+        // lets inform other views what's the current SQL editor
+        let currentQueryIndex = String(this.currentQuery);
+        this.store.dispatch(new appActions.setEditorIndex(currentQueryIndex));
+        this.dataverseSelected();
+        this.editor.focus();
+    }
+
+    onClickClear() {
+        let queryClear = {
+            editorId: String(this.currentQuery),
+            queryString: ""
+        };
+        this.store.dispatch(new sqlQueryActions.CleanQuery(queryClear));
+        this.queryErrorMessageString = "";
+        this.queryString = "";
+        this.metricsString = "";
+        this.editor.getDoc().setValue(this.queryString);
+        this.editor.focus();
+    }
+
+    onClickPrevious() {
+        if (this.currentQuery > 0) {
+            this.nextSQLEditor(-1);
+        }
+    }
+
+    onClickNext() {
+        if (this.currentQuery < this.preparedQueryCount - 1) {
+            this.nextSQLEditor(1);
+        }
+    }
+
+    checkNext() {
+        if (this.currentQuery == this.preparedQueryCount - 1) {
+          return true;
+        } else {
+          return false;
+        }
+    }
+
+    checkPrevious() {
+        if (this.currentQuery == 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    nextSQLEditor(next) {
+        // Saving First
+        this.queryPrepare = {
+            editorId: String(this.currentQuery),
+            queryString: this.queryString
+        };
+        this.store.dispatch(new sqlQueryActions.PrepareQuery(this.queryPrepare));
+
+        this.currentQuery = this.currentQuery + next;
+        this.queryErrorMessageString = "";
+        this.metricsString = "";
+
+        // Retrieve Metrics or Error Message if Query was executed
+        this.showMetrics();
+
+        // Retrieve Metrics or Error Message if Query was executed
+        this.showErrors();
+
+        // Retrieve the prepared SQL string
+        this.queryString = this.queryPrepared[this.currentQuery];
+        this.editor.getDoc().setValue(this.queryString);
+
+        // lets inform other views what's the current SQL editor
+        let currentQueryIndex = String(this.currentQuery);
+
+        // Inform the app we are now active in next editor
+        this.store.dispatch(new appActions.setEditorIndex(currentQueryIndex));
+    }
+
+    onClickInputCardCollapse() {
+        this.collapse = !this.collapse;
+        if (this.collapse) {
+            this.input_expanded_icon = 'expand_more';
+        } else {
+            this.input_expanded_icon = 'expand_less';
+        }
+    }
+
+    /**
+     * On component view init
+     */
+    @ViewChild('editor') editor: CodeMirror.Editor;
+    ngAfterViewInit() {
+        this.codemirrorInit(this.codemirrorConfig);
+    }
+
+    /**
+     * Initialize codemirror
+     */
+    codemirrorInit(config) {
+        this.editor = CodeMirror.fromTextArea(this.editor.nativeElement, config);
+        this.editor.setSize(null, 'auto');
+        this.editor.getDoc().setValue(this.queryString);
+        this.editor.on('changes', () => {
+            this.queryString = this.editor.getValue();
+        });
+    }
+
+    dataverseSelected() {
+        if (this.selected == undefined) {
+            this.queryString = '';
+        } else {
+            this.queryString = 'Use ' + this.selected + '; ';
+        }
+        this.editor.getDoc().setValue(this.queryString);
+        this.editor.focus();
+    }
+
+    onClickNextHistory() {
+        if (this.currentHistory < this.history.length - 1) {
+          this.currentHistory++;
+          this.viewCurrentHistory++;
+          this.queryString = this.history[this.currentHistory];
+          this.editor.getDoc().setValue(this.queryString);
+          this.editor.focus();
+        }
+    }
+
+    onClickPrevHistory() {
+        if (this.currentHistory > 0) {
+            this.currentHistory--;
+            this.viewCurrentHistory--;
+            this.queryString = this.history[this.currentHistory];
+            this.editor.getDoc().setValue(this.queryString);
+            this.editor.focus();
+        }
+    }
+
+    onClickMetadata() {
+        this.sideMenuVisible = !this.sideMenuVisible;
+        this.store.dispatch(new appActions.setSideMenuVisible(this.sideMenuVisible));
+    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3e5815a7/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata-inspector.component.html
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata-inspector.component.html b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata-inspector.component.html
new file mode 100644
index 0000000..cd38636
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata-inspector.component.html
@@ -0,0 +1,22 @@
+<!--/*
+Licensed 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="inspector-dialog">
+    <p mat-dialog-title class="header">METADATA INSPECTOR</p>
+    <mat-dialog-content>
+        <pre class="content">{{data}}</pre>
+    </mat-dialog-content>
+    <mat-action-row>
+        <button mat-button class='input-button' (click)="onClickClose()">CLOSE</button>
+    </mat-action-row>
+</div>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3e5815a7/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata-inspector.component.scss
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata-inspector.component.scss b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata-inspector.component.scss
new file mode 100644
index 0000000..fd6f01d
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata-inspector.component.scss
@@ -0,0 +1,30 @@
+/*
+Licensed 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.
+*/
+
+.inspector-dialog {
+    font-size: 0.80rem;
+    font-weight: 500;
+}
+
+.header {
+    font-size: 1.0rem;
+    font-weight: 500;
+    color: blue;
+    border-bottom: 1px solid rgb(145, 152, 158);
+}
+
+.content {
+    margin-left: auto !important;
+    margin-right: auto !important;
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3e5815a7/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata.component.html
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata.component.html b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata.component.html
index 4641426..056ff44 100755
--- a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata.component.html
+++ b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata.component.html
@@ -11,34 +11,53 @@ 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.
 */ -->
-<mat-card class="metadata-card">
-  <mat-toolbar color="primary" class="metadata-selector">
-    <mat-icon class="example-icon">menu</mat-icon>
-    <span>METADATA GUIDE</span>
-    <span class="spacer"></span>
-  </mat-toolbar>
-    <div class="metadata-content-area">
-    <div class="metadata-tree">
-      <div class="metadata-all">
-          <p-tree [style]="{'width':'100%', 'border': 'none', 'font-family': 'Roboto Mono', 'font-size': '0.80rem',
-          'font-weight': '500'}" selectionMode="single" [value]="nodesAll" (onNodeSelect)="nodeSelectAll($event)"></p-tree>
-      </div>
-      <div class="metadata-datasets">
-          <p-tree [style]="{'width':'100%', 'border': 'none', 'font-family': 'Roboto Mono', 'font-size': '0.80rem',
-          'font-weight': '500'}" selectionMode="single" [value]="nodesDatasets" (onNodeSelect)="nodeSelectDataset($event)"></p-tree>
-      </div>
-      <div class="metadata-datatypes">
-          <p-tree [style]="{'width':'100%', 'border': 'none', 'font-family': 'Roboto Mono', 'font-size': '0.80rem',
-          'font-weight': '500'}" selectionMode="single" [value]="nodesDatatypes"></p-tree>
-      </div>
-      <div class="metadata-index">
-          <p-tree [style]="{'width':'100%', 'border': 'none', 'font-family': 'Roboto Mono', 'font-size': '0.80rem',
-          'font-weight': '500'}" selectionMode="single" [value]="nodesIndexes"></p-tree>
-      </div>
-
-    </div>
-  </div>
-  <!--<mat-card-actions class="actions">
-     <button mat-button class="refresh-button" (click)="menuRefresh()">COLLAPSE</button>
-  </mat-card-actions> -->
-</mat-card>
+<div class="wrapper">
+    <mat-expansion-panel hideToggle [expanded]="true">
+        <mat-expansion-panel-header class="header-dataverse">
+        <mat-icon>developer_board</mat-icon>
+        <mat-panel-title>DATAVERSES</mat-panel-title>
+        <mat-panel-description></mat-panel-description>
+        </mat-expansion-panel-header>
+        <section class="section">
+        <li *ngFor="let dataverse of dataverses; index as i">
+            <mat-checkbox [labelPosition]="before" class="margin" (change)="generateFilter(dataverse.DataverseName, $event, value, i)" [(ngModel)]="dataverse.active">{{dataverse.DataverseName}}</mat-checkbox>
+        </li>
+        <div class="refresh">
+            <button mat-button class="refresh-button" (click)="refreshMetadata()" matTooltip="Click to refresh changes in AsterixDB"><mat-icon class="list-icon">cached</mat-icon>REFRESH</button>
+        </div>
+        </section>
+    </mat-expansion-panel>
+    <mat-expansion-panel hideToggle [expanded]="panelOpenState">
+        <mat-expansion-panel-header #datasetsPanel class="header">
+            <mat-icon>developer_board</mat-icon>
+            <mat-panel-title class="title">DATASETS</mat-panel-title>
+            <mat-panel-description></mat-panel-description>
+        </mat-expansion-panel-header>
+        <section class="section">
+        <li *ngFor="let dataset of datasetsFiltered" (click)="openMetadataInspectorDialog(dataset)">
+            {{dataset.DatasetName}}</li>
+        </section>
+    </mat-expansion-panel>
+    <mat-expansion-panel hideToggle [expanded]="panelOpenState">
+        <mat-expansion-panel-header class="header">
+            <mat-icon>developer_board</mat-icon>
+            <mat-panel-title class="title">DATATYPES</mat-panel-title>
+            <mat-panel-description></mat-panel-description>
+        </mat-expansion-panel-header>
+        <section class="section">
+        <li *ngFor="let datatype of datatypesFiltered" (click)="openMetadataInspectorDialog(datatype)">
+            {{datatype.DatatypeName}}</li>
+        </section>
+    </mat-expansion-panel>
+    <mat-expansion-panel hideToggle [expanded]="panelOpenState">
+        <mat-expansion-panel-header class="header">
+            <mat-icon>developer_board</mat-icon>
+            <mat-panel-title class="title">INDEX</mat-panel-title>
+            <mat-panel-description></mat-panel-description>
+        </mat-expansion-panel-header>
+        <section class="section">
+        <li *ngFor="let index of indexesFiltered" (click)="openMetadataInspectorDialog(index)">
+            {{index.IndexName}}</li>
+        </section>
+    </mat-expansion-panel>
+</div>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3e5815a7/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata.component.scss
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata.component.scss b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata.component.scss
index 4ee2339..6cd5966 100755
--- a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata.component.scss
+++ b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata.component.scss
@@ -11,87 +11,80 @@ 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.
 */
-$metadata-spacing-unit: 5px;
 
-.metadata-card {
-	display: flex;
-	flex-flow: column;
-	padding: 0;
-	margin: 0 auto; //($metadata-spacing-unit * 2);
-	margin-top: ($metadata-spacing-unit * 2);
-	margin-bottom: ($metadata-spacing-unit * 2);
-	min-height: 150px;
-	box-shadow: none !important;
-	width: 92%;
-	overflow: hidden;
+mat-checkbox .mat-icon {
+    transform: scale(1);
 }
 
-.example-icon {
-	padding: 0 14px 0 0;
-	margin: 0;
+.section {
+    font-size: 0.80rem;
+    font-weight: 500;
+    li {
+        list-style-type: none;
+        color: #3E3E30;
+        cursor: pointer;
+        &:hover {
+            color: blue;
+        }
+        overflow: hidden !important;
+        text-overflow: ellipsis !important;
+        word-break: break-all;
+        white-space: nowrap;
+    }
 }
 
-.spacer {
-  flex: 1 1 auto;
+.wrapper {
+    width: 300px;
+    font-size: 0.80rem;
+    font-weight: 500;
+    text-align: left;
+    padding-left: 5px;
+    padding-right: 10px;
+    padding-bottom: 5px;
+    padding-top: 5px;
+    //background-color: gainsboro;
+    background-color: black;
+    margin-bottom: 50px;
+    mat-expansion-panel {
+        border: none !important;
+    }
 }
 
-.metadata-selector {
-	min-height: 42px;
-	max-height: 42px;
-	justify-content: center;
-	//align-items: center;
-	font-size: 0.80rem;
-	font-weight: 500;
-	background-color: white;
-	border: 1px solid rgba(54, 147, 209, 0.87);
+.header {
+    font-size: 0.80rem;
+    font-weight: 500; // color:rgb(145, 152, 158);
+    border-top: 1px solid rgb(145, 152, 158);
+    display: flex;
+    flex-flow: row;
+    align-items: center;
+    max-height: 42px;
+    min-height: 42px;
+    color: blue;
 }
 
-.metadata-content-area {
-	padding: ($metadata-spacing-unit * 2);
-	margin: 0;
+.header-dataverse {
+    font-size: 0.80rem;
+    font-weight: 500;
+    max-height: 42px;
+    min-height: 42px;
+    color: blue;
 }
 
-.metadata-tree {
-	min-height: 30px;
-	font-size: 0.80rem;
-	font-weight: 500;
+.title {
+    color:blue;
 }
 
-.metadata-datasets {
-	margin-top: ($metadata-spacing-unit * 2);
-	margin-bottom: ($metadata-spacing-unit * 2);
-}
-
-.metadata-datatypes {
-	margin-top: ($metadata-spacing-unit * 2);
-	margin-bottom: ($metadata-spacing-unit * 2);
-}
-
-.metadata-dataindexes {
-	margin-top: ($metadata-spacing-unit * 2);
-	margin-bottom: ($metadata-spacing-unit * 2);
-}
-
-
-.metadata-tree.ui-tree {
-	//width: 260px !important;
-	font-size: 0.80rem;
-	font-weight: 500;
-	border: none !important;
-	background-color: red;
+.list-icon {
+    font-size: 18px;
 }
 
 .refresh-button {
-	float: left;
-	margin-top: $metadata-spacing-unit;
+    font-size: 12px !important;
 }
 
-.actions {
-	border-top: 1px solid rgba(0, 0, 0, 0.1);
-	color: rgba(54, 147, 209, 0.87);
-	padding: $metadata-spacing-unit;
-	margin: 0;
+.refresh {
+    margin-top: 15px;
+    display: flex;
+    flex-flow: row;
+    align-items: center;
 }
-
-
-

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3e5815a7/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata.component.ts
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata.component.ts b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata.component.ts
index e60c9de..2271dda 100755
--- a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata.component.ts
+++ b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/metadata.component.ts
@@ -11,199 +11,156 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
-import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
-import { Router } from '@angular/router';
-import { Dataverse } from '../../shared/models/asterixDB.model';
+import { Component, Inject } from '@angular/core';
 import { Store } from '@ngrx/store';
-import { Observable } from 'rxjs/Observable';
+import { Observable } from 'rxjs';
 import * as dataverseActions from '../../shared/actions/dataverse.actions';
 import * as datasetActions from '../../shared/actions/dataset.actions';
 import * as datatypesActions from '../../shared/actions/datatype.actions';
 import * as indexesActions from '../../shared/actions/index.actions';
-import * as metadataActions from '../../shared/actions/metadata.actions';
-import * as datasetsActions from '../../shared/actions/dataset.actions';
-import { ElementRef, ViewChild} from '@angular/core';
-import {DataSource} from '@angular/cdk/collections';
-import {BehaviorSubject} from 'rxjs/BehaviorSubject';
-import 'rxjs/add/operator/startWith';
-import 'rxjs/add/observable/merge';
-import 'rxjs/add/operator/map';
-import 'rxjs/add/operator/debounceTime';
-import 'rxjs/add/operator/distinctUntilChanged';
-import 'rxjs/add/observable/fromEvent';
-import { Subscription } from 'rxjs/Rx';
-import * as fromRoot from '../../shared/reducers/dataverse.reducer';
-import { State } from '../../shared/reducers/dataverse.reducer';
-import { TreeModule, TreeNode} from 'primeng/primeng';
-
-
-/**
- * query component
- * has editor (codemirror) for writing some query
- */
+import { ViewChild} from '@angular/core';
+import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
+
 @Component({
-	moduleId: module.id,
-	selector: 'awc-metadata',
-	templateUrl: 'metadata.component.html',
-	styleUrls: ['metadata.component.scss']
+    moduleId: module.id,
+    selector: 'awc-metadata',
+    templateUrl: 'metadata.component.html',
+    styleUrls: ['metadata.component.scss']
 })
 
-export class MetadataComponent implements OnInit {
-	nodesAll = [];
-	nodesDatasets = [];
-	nodesDatatypes = [];
-	nodesIndexes = [];
-
-	constructor(private store: Store<any>, private changeDetector: ChangeDetectorRef) {}
-
-	ngOnInit(): void {
-
-		// Watching for the metadata tree
-		this.store.select(s => s.metadata.tree).subscribe((data: any[]) => {
-			
-			this.nodesAll = [];
-			this.nodesDatasets = [];
-			this.nodesDatatypes = [];
-			this.nodesIndexes = [];
-			const indexesMenu = [];
-			const datatypesMenu = [];
-			const datasetsMenu = [];
-			const dataversesRoot = { label: '', children: []};
-			dataversesRoot.label = 'DATAVERSES';
-			dataversesRoot.children = [];
-
-			for (let i = 0; i < data.length; i++) {
-
-				// Don't want to show metadata system datasets, datatypes or indexes
-			// if (data[i]['DataverseName'] && data[i]['DataverseName'] !== "Metadata" )
-			//	{
-					// Counting dataverses to align the menu identifiers
-			    	const dataverse = { label: '', children: [] }; 
-					dataverse.label = data[i]['DataverseName'];
-					dataversesRoot.children.push(dataverse);
-
-					// Adding the datasets to correspondent dataverse
-					if (data[i]['Datasets'].length) {
-						const datasetRoot = { label: '', children: [] }; 
-						datasetRoot.label = 'DATASETS';
-						dataverse.children.push(datasetRoot);
-						for (let j = 0; j < data[i]['Datasets'].length; j++) {
-							const dataset = { label: '', children: [] }; 
-							dataset.label = data[i]['Datasets'][j]['DatasetName'];
-
-							//
-							// Adding the datatype to correspondent dataset
-							//
-							if (data[i]['Datasets'][j]['Datatype']) {
-								const datatypeRoot = { label: '', children: [] };
-								datatypeRoot.label = 'Datatype: ' + data[i]['Datasets'][j]['Datatype']['DatatypeName'];
-								//
-								// Looking for the datatype fields
-								//
-								if (data[i]['Datasets'][j]['Datatype']['Derived']) {
-									if (data[i]['Datasets'][j]['Datatype']['Derived']['Record']) { 
-										const datatypeFieldsRoot = { label: '', leaf: true, expanded: true, children: [] };
-										datatypeFieldsRoot.label = 'FIELDS';
-										for (let k = 0; k < data[i]['Datasets'][j]['Datatype']['Derived']['Record']['Fields'].length; k++) {
-											const datatypeField = { label: '', children: [] }; 
-											datatypeField.label = data[i]['Datasets'][j]['Datatype']['Derived']['Record']['Fields'][k]['FieldName'] + ": " + data[i]['Datasets'][j]['Datatype']['Derived']['Record']['Fields'][k]['FieldType'];
-											datatypeFieldsRoot.children.push(datatypeField);
-										}
-										datatypeRoot.children.push(datatypeFieldsRoot);
-
-									}
-								}
-								dataset.children.push(datatypeRoot);
-
-								datatypeRoot.label = data[i]['Datasets'][j]['Datatype']['DatatypeName'];
-								datatypesMenu.push(datatypeRoot);
-							}
-
-							//
-							// Adding the indexes to correspondent dataset
-							//
-							if (data[i]['Datasets'][j]['Indexes'].length) {
-								const indexRoot = { label: '', children: [] }; 
-								indexRoot.label = 'INDEXES';
-								
-								for (let k = 0; k < data[i]['Datasets'][j]['Indexes'].length; k++) {
-									const indexChild = { label: '', children: [] }; 
-									indexChild.label = data[i]['Datasets'][j]['Indexes'][k]['IndexName'];
-
-									// is Primary
-									const indexIsPrimaryRoot = { label: '', children: [] };
-									indexIsPrimaryRoot.label = 'isPrimary' + ': ' + data[i]['Datasets'][j]['Indexes'][k]['IsPrimary'];
-									indexChild.children.push(indexIsPrimaryRoot);
-								
-									// SearchKey
-									if (data[i]['Datasets'][j]['Indexes'][k]['SearchKey']) {
-										const indexSearchKeyRoot = { label: '', children: [] };
-										indexSearchKeyRoot.label = 'SEARCH KEY';
-										for (let l = 0; l < data[i]['Datasets'][j]['Indexes'][k]['SearchKey'].length; l++) {
-											const indexsearchKeyField = { label: '', children: [] };
-											indexsearchKeyField.label = data[i]['Datasets'][j]['Indexes'][k]['SearchKey'][l]
-											indexSearchKeyRoot.children.push(indexsearchKeyField);
-										}
-
-										indexChild.children.push(indexSearchKeyRoot);
-										indexesMenu.push(indexChild);
-									}
-
-									indexRoot.children.push(indexChild);
-								}
-
-								dataset.children.push(indexRoot);
-								datasetRoot.children.push(dataset);
-								datasetsMenu.push(dataset);
-							}
-						}
-					}
-			//	}
-			}
-			
-			this.nodesAll.push(dataversesRoot);
-
-			/*
-			* Making the rest of the stand alone submenus
-			*/
-
-			// Adding the DATASET stand alone submenu
-			const datasetMenuRoot = { label: '', children: [] };
-			datasetMenuRoot.label = 'DATASETS';
-			datasetMenuRoot.children = datasetsMenu;
-			this.nodesDatasets.push(datasetMenuRoot);
-
-			// Adding the DATATYPES stand alone submenu
-			const datatypeMenuRoot = { label: '', children: [] };
-			datatypeMenuRoot.label = 'DATATYPES';
-			datatypeMenuRoot.children = datatypesMenu;
-			this.nodesDatatypes.push(datatypeMenuRoot);
-
-			// Adding the DATATYPE stand alone submenu
-			const indexesMenuRoot = { label: '', children: [] };
-			indexesMenuRoot.label = 'INDEXES';
-			indexesMenuRoot.children = indexesMenu;
-			this.nodesIndexes.push(indexesMenuRoot);
-
-			// Component View Refresh
-			this.changeDetector.detectChanges();
-		});
-	}
-
-	/*
-	* UI helpers to select dataverses from the guide menu
-	*/
-	nodeSelectAll(event) {
-		if (event.node.parent && event.node.parent.label === 'DATASETS') {
-			const datasetName = event.node.label.replace(/-;-/g);
-			this.store.dispatch(new datasetsActions.GuideSelectDatasets(datasetName));
-		}
-	}
-	
-	nodeSelectDataset(event) {
-		if (event.node.parent && event.node.parent.label === 'DATASETS') {
-			const datasetName = event.node.label.replace(/-;-/g);
-			this.store.dispatch(new datasetsActions.GuideSelectDatasets(datasetName));
-		}
-	}
+export class MetadataComponent {
+    dataverses$: Observable<any>;
+    dataverses: any;
+    datasetsFiltered: any;
+    datasets$: Observable<any>;
+    datasets: any;
+    datatypesFiltered :any;
+    datatypes$: Observable<any>;
+    datatypes: any;
+    indexesFiltered: any;
+    indexes$: Observable<any>;
+    indexes: any;
+
+    constructor(private store: Store<any>, public dialog: MatDialog) {
+        this.refreshMetadata();
+    }
+
+    ngOnInit() {
+        this.dataverses$ = this.store.select(s => s.dataverse.dataverses.results);
+
+         // Watching for Dataverses
+         this.dataverses$ = this.store.select(s => s.dataverse.dataverses.results);
+         this.dataverses$.subscribe((data: any[]) => {
+             this.dataverses = data;
+         });
+
+         // Watching for Datasets
+         this.datasets$ = this.store.select(s => s.dataset.datasets.results);
+         this.datasets$.subscribe((data: any[]) => {
+                this.datasets = data;
+                this.datasetsFiltered = this.filter(this.datasets);
+         });
+
+         // Watching for Datatypes
+         this.datatypes$ = this.store.select(s => s.datatype.datatypes.results);
+         this.datatypes$.subscribe((data: any[]) => {
+            this.datatypes = data;
+            this.datatypesFiltered = this.filter(this.datatypes);
+         });
+
+         // Watching for indexes
+         this.indexes$ = this.store.select(s => s.index.indexes.results);
+         this.indexes$.subscribe((data: any[]) => {
+            this.indexes = data;
+            this.indexesFiltered = this.filter(this.indexes);
+         });
+    }
+
+    refreshMetadata() {
+        this.store.dispatch(new dataverseActions.SelectDataverses('-'));
+        this.store.dispatch(new datasetActions.SelectDatasets('-'));
+        this.store.dispatch(new datatypesActions.SelectDatatypes('-'));
+        this.store.dispatch(new indexesActions.SelectIndexes('-'));
+    }
+
+    dataverseFilter = {}
+    dataverseFilterMap = new Map();
+
+    filter(data){
+        let results = [];
+
+        if (data) {
+            for (let i=0; i< data.length; i++){
+                let keyCompare = data[i].DataverseName
+                this.dataverseFilterMap.forEach((value: boolean, key: string) => {
+                    if (keyCompare === key) {
+                        results.push(data[i]);
+                    }
+                });
+            }
+        }
+        return results;
+    }
+
+    @ViewChild('datasetsPanel') datasetsPanel;
+    panelOpenState: boolean = false;
+
+    checkStatus = [];
+    generateFilter(dataverse, event, i) {
+
+        if (this.checkStatus[i] == undefined) {
+            this.checkStatus.push(event.checked);
+        } else {
+            this.checkStatus[i] = event.checked;
+        }
+
+        if (event.checked === true) {
+            this.dataverseFilter[dataverse] = event.checked;
+            this.dataverseFilterMap.set(dataverse, event.checked);
+        } else {
+            delete this.dataverseFilter[dataverse];
+            this.dataverseFilterMap.delete(dataverse);
+        }
+
+        this.datasetsFiltered = this.filter(this.datasets);
+        this.datatypesFiltered = this.filter(this.datatypes);
+        this.indexesFiltered = this.filter(this.indexes);
+
+        /* Open the dataset expansion panel if there is anything to show */
+        if (this.datasetsFiltered.length > 0) {
+            this.panelOpenState = true;
+        } else {
+            this.panelOpenState = false;
+        }
+    }
+
+    /*
+    * opens the metadata inspector
+    */
+    openMetadataInspectorDialog(data): void {
+        let metadata = JSON.stringify(data, null, 8);
+        metadata = metadata.replace(/^{/, '');
+        metadata = metadata.replace(/^\n/, '');
+        metadata = metadata.replace(/}$/, '');
+        let dialogRef = this.dialog.open(DialogMetadataInspector, {
+            width: '500px',
+            data: metadata,
+            hasBackdrop: false
+        });
+    }
+}
+
+@Component({
+    selector: 'dataset-create-dialog',
+    templateUrl: 'metadata-inspector.component.html',
+    styleUrls: ['metadata-inspector.component.scss']
+})
+
+export class DialogMetadataInspector {
+    constructor(  public dialogCreateDsRef: MatDialogRef<DialogMetadataInspector>,
+                  @Inject(MAT_DIALOG_DATA) public data: any) { }
+
+    onClickClose() {
+        this.dialogCreateDsRef.close();
+    }
 }

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3e5815a7/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/ouput.component.ts
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/ouput.component.ts b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/ouput.component.ts
deleted file mode 100755
index fcfc235..0000000
--- a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/ouput.component.ts
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-import { Component, OnInit, ViewChild,  AfterViewInit, ChangeDetectorRef, Pipe, PipeTransform } from '@angular/core';
-import { Observable } from 'rxjs/Observable';
-import { Store } from '@ngrx/store';
-import * as sqlQueryActions from '../../shared/actions/query.actions'
-import { saveAs } from 'file-saver';
-import { DomSanitizer } from '@angular/platform-browser';
-import {TreeModule,TreeNode} from 'primeng/primeng';
-
-/**
- * query component
- * has editor (codemirror) for writing some query
- */
-
-@Pipe({ name: 'safeHtml'})
-export class SafeHtmlPipe implements PipeTransform  {
-  constructor(private sanitized: DomSanitizer) {}
-  transform(value) {
-    return this.sanitized.bypassSecurityTrustHtml(value);
-  }
-}
-
-@Component({
-	moduleId: module.id,
-	selector: 'awc-results',
-	templateUrl:'output.component.html',
-	styleUrls: ['output.component.scss']
-})
-
-
-export class QueryOutputComponent implements OnInit {
-	queryMessage: string;
-	treeData = [];
-	flattenData = [];
-	dataColumns = [];
-	query_message: string;
-	execution_time: number;
-	loaded$: Observable<any>
-	data: any[];
-	loading: Boolean;
-	jsonOutput = "";
-	selectedOutputView = "NONE";
-	outputQueryString = "";
-	toogleExpand = "EXPAND TREE"
-	
-	/* Codemirror configuration */
-	codemirrorConfig = 	{ 	mode: "asterix",
-		lineWrapping: true,
-		showCursorWhenSelecting: true
-	};
-
-	generateTreeMenu(node, rootMenu): any {
-
-		// Check in case the root object is not defined properly
-		if (rootMenu === undefined) {
-			rootMenu = { label: '', children: []};
-		}
-
-		let nodeArray = [];
-		
-		// Going through all the keys in a node looking for objects or array of key values
-		// and create a sub menu if is an object.
-		Object.keys(node).map((k) => {		
-
-			if (typeof node[k] === 'object') {
-				let nodeObject = { label: '', children: []};
-				nodeObject = { label: '', children: []};
-				nodeObject.label = k;
-				// if this is an object then a new node is created and
-				// recursive call to find and fill with the nested elements
-				let newNodeObject = this.generateTreeMenu(node[k], nodeObject);
-
-				// if this is the first node, then will become the root.
-				if (rootMenu.children) {
-					rootMenu.children.push(newNodeObject)
-				} else {
-					rootMenu = newNodeObject
-				}
-			}
-			else {
-				// Array of key values converted into a unique string with a : separator 
-				let nodeKeyValue = { label: '', children: []};
-				nodeKeyValue.label = k + " : " + node[k]
-				nodeArray.push(nodeKeyValue);
-			}
-		})
-
-		// The array will be added as value to a parent key.
-		if (nodeArray.length > 0) {
-			rootMenu.children = nodeArray.concat(rootMenu.children)
-		}
-		
-		return rootMenu 
-	}
-
-	constructor(private store: Store<any>, private changeDetector: ChangeDetectorRef) {
-		this.loaded$ = this.store.select(s => s.sqlQuery.loaded);
-		this.store.select("sqlQuery").subscribe((data: any) => {
-			// Set the output toolbar query string and default view settings
-			if (data.loaded) {
-				this.selectedOutputView = "TABLE";
-				this.loading = true;
-				this.data = data.sqlQueryResult.results;
-				this.treeData = [];
-				let stringQuery = data.sqlQueryString;
-	
-				// Preparing the toolbar 
-				if (stringQuery.length > 150) {
-					this.outputQueryString = ": " + stringQuery.slice(0, 150) + " (..)"
-				} else {
-					this.outputQueryString = ": " + stringQuery;
-				}
-
-				// Processing the results 
-				if (data.sqlQueryResult.results && data.sqlQueryResult.results.length > 0 && this.data[0]) {
-
-					/* Removing the root object, disabled for the time being 
-					var resultKeyList = Object.keys(this.data[0]);
-					var resultKey: string = resultKeyList[0]; 
-					*/
-
-					for (let i = 0; i < this.data.length; i++) {
-
-						/* Removing the root object, disabled for the time being 
-						if (this.data[i][resultKey] instanceof Object) {	
-							this.data[i] = this.data[i][resultKey];
-						}*/	
-
-						let nodeContent = { label:"[" + i + "]" , children: []};
-						this.treeData.push(this.generateTreeMenu(this.data[i], nodeContent))
-					}
-
-					this.loading = false;
-				} 
-	
-				// JSON OUTPUT
-				// Making into a JSON String for JSON String Output
-				this.jsonOutput = JSON.stringify(data.sqlQueryResult.results, null, 2)
-				
-				// TABLE OUTPUT
-				if (this.data && this.data.length > 0) {
-
-					this.collapseAll();
-					// Normalize the data ( removing the first key if is an object )
-					// TODO: Move it into a recursive function.
-					this.dataColumns = [];
-
-					var resultKeyList = Object.keys(this.data[0]);
-					var resultKey: string = resultKeyList[0]; 
-					if (this.data[0][resultKey] instanceof Object) {	
-						// is a SQL++ Query Results 
-						var nestedKeyList = Object.keys(this.data[0][resultKey]);
-						for (let i = 0; i < nestedKeyList.length; i++) {
-							if (typeof this.data[0][resultKey][nestedKeyList[i]] === 'object') {
-								// Creating a key to display a nested type
-								this.dataColumns.push({field: 'nestedString' + i, header: nestedKeyList[i]})
-								 				
-							} else {
-								this.dataColumns.push({field: nestedKeyList[i], header: nestedKeyList[i] })
-							}
-							
-						}
-					}
-					else { // is a SQL++ Metadata Results and there is an Array
-						for (let i = 0; i < resultKeyList.length; i++) {
-							this.dataColumns.push({field: resultKeyList[i], header: resultKeyList[i] })
-						}
-					}
-
-					// Now prepare the data ( SQL++ Query, Metatada Queries no need to change anything ).
-					// TODO: Move it into a recursive function.
-					if (this.data[0][resultKey] instanceof Object) {	
-						// is a SQL++ Query Results 
-						for (let i = 0; i < this.data.length; i++) {
-
-							// // is a SQL++ Query Results 
-							var nestedKeyList = Object.keys(this.data[i][resultKey]);
-							for (let k = 0; k < nestedKeyList.length; k++) {
-								if ( typeof this.data[i][resultKey][nestedKeyList[k]] === 'object' ){
-										// Creating a display value to for a nested type JSON.stringify(jsObj, 
-										var nestedObjectStr = JSON.stringify(this.data[i][resultKey][nestedKeyList[k]], null, '\n');
-										var nestedKey = 'nestedString' + k;
-										this.data[i][resultKey][nestedKey] = nestedObjectStr; 				
-								} 
-							}
-
-							this.data[i] = this.data[i][resultKey];
-						}	
-					}
-				}
-			}
-      	});
-	}
-
-	/* 
-	* Subscribing to store values
-	*/
-	ngOnInit(): void {
-		this.loaded$ = this.store.select('sqlQuery');
-		this.store.select("sqlQuery").subscribe((data: any) => {
-			if (data.sqlQueryError.errors){
-				this.queryMessage = data.sqlQueryError.errors[0].msg
-			}else{
-				this.queryMessage = ""
-			}
-		})
-	}
-
-	/* 
-	* Changes view mode [ TABLE, TREE, JSON VIEW ]
-	*/
-	onSelect(value: any) {
-		this.selectedOutputView = value;		
-	}
-
-	/* 
-	* Export to CSV 
-	*/
-    exportToCSV(){
-		var blob = new Blob([this.jsonOutput], {type: "text/csv;charset=utf-8"});
-		saveAs(blob, "Asterix-results.csv");
-	}
-	
-	/*
-	*  Export to plain text
-	*/
-    exportToText(){
-		var exportOutput = this.jsonOutput;
-		var blob = new Blob([exportOutput], {type: "text/plain;charset=utf-8"});
-		saveAs(blob, "Asterix-results.txt");
-	}
-	
-	/*
-	*  Expand/Collapse Tree
-	*/
-    expandTree(){
-		if (this.toogleExpand === "EXPAND TREE"){
-			this.expandAll();
-		} else {
-			this.collapseAll();
-		}
-	}
-	
-	expandAll(){
-		this.toogleExpand = "TREE COLLAPSE";
-        this.treeData.forEach( node => {
-            this.expandRecursive(node, true);
-        } );
-    }
-
-    collapseAll(){
-		this.toogleExpand = "EXPAND TREE";
-        this.treeData.forEach( node => {
-            this.expandRecursive(node, false);
-        } );
-    }
-    
-    private expandRecursive(node:TreeNode, isExpand:boolean){
-        node.expanded = isExpand;
-        if(node.children){
-            node.children.forEach( childNode => {
-                this.expandRecursive(childNode, isExpand);
-            } );
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3e5815a7/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/output.component.html
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/output.component.html b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/output.component.html
index f7c4b43..01a4a0a 100755
--- a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/output.component.html
+++ b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/output.component.html
@@ -12,57 +12,17 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */ -->
 <mat-card class="sql-results-card">
-	<mat-toolbar color="primary" class="results-selector">
-		<mat-icon class="toolbar-icon">menu</mat-icon>
-	    <span class="output-query-string">OUTPUT{{outputQueryString}}</span>
-		<span class="spacer"></span>
-	</mat-toolbar>
-  	<mat-card-content class="content-area">
-		<div *ngIf="loaded$ | async as ld">
-			<div *ngIf="selectedOutputView=='TABLE'">				
-				<p-dataTable [style]="{'width':'100%', 'overflow':'hidden'}" id='review-table' [responsive]="true" [hidden]="loading" [value]="data" [rows]="20" [paginator]="true" [pageLinks]="3" [rowsPerPageOptions]="[5,10,20, 30, 40, 50]" >
-					<p-column [style]="{'text-align':'left',
-					'text-overflow': 'ellipsis', 'word-wrap': 'break-word', 'word-break': 'break-all'}"
-					
-					[footerStyle]="{'color':'blue'}" [headerStyleClass]="datatable-header" *ngFor="let node of dataColumns;" [field]="node.field" 
-					[header]="node.header" [sortable]="true">
-					</p-column>
-				</p-dataTable>
-			</div>
-		</div>
-		<div *ngIf="loaded$ | async as ld">	
-			<div *ngIf="ld.sqlQueryError.metrics" class="queryErrorMessage">
-				<span>ERROR:</span>
-				<span>{{queryMessage}}</span>
-			</div>	
-			 <div [hidden]="selectedOutputView!='TREE'" class="data-viewer-container">
-				<button mat-button class="button-expand" (click)="expandTree()">{{toogleExpand}}</button>
-				<p-tree [style]="{'width':'100%', 'border': 'none', 'font-family': 'Roboto Mono', 'font-size': '0.80rem',
-					'font-weight': '500'}" [value]="treeData"></p-tree>
-			</div>
-			<div *ngIf="loaded$ | async as ld">	
-				<div *ngIf="selectedOutputView=='JSON'" class="data-viewer-container">
-					<button mat-button class="button-export" (click)="exportToText()">EXPORT</button>
-					<pre class="json-output">{{jsonOutput}}</pre>
-				</div>
-			</div>
-		</div>
-	</mat-card-content>
-	<mat-card-actions class="actions">
-		<div *ngIf="loaded$ | async as ld">
-			<span *ngIf="ld.sqlQueryResult.metrics" class="metrics">
-				<span class="span-results">SUCCESS:</span>
-				<span class="span-results">Count: {{ld.sqlQueryResult.metrics.resultCount}}</span>
-				<span class="span-results">Size: {{ld.sqlQueryResult.metrics.resultSize}}</span>
-				<span class="span-results">Elapsed time: {{ld.sqlQueryResult.metrics.elapsedTime}}</span>
-				<span class="span-results">Execution time: {{ld.sqlQueryResult.metrics.executionTime}}</span>
-				<span class="spacer"></span>
-				<mat-button-toggle-group #group="matButtonToggleGroup" class="output-group" value={{selectedOutput}} (change)="onSelect(group.value)">
-					<mat-button-toggle mat-button  value="TABLE">TABLE</mat-button-toggle>
-					<mat-button-toggle mat-button  value="TREE">TREE</mat-button-toggle>
-					<mat-button-toggle mat-button  value="JSON">JSON</mat-button-toggle>
-				</mat-button-toggle-group>
-			</span>
-		</div>
-	</mat-card-actions>
+    <mat-card-content class="content-area">
+        <div class="divider">
+        <div *ngIf='data.length != 0'>
+            <tree-view [data]="data" [queryId]="queryId"></tree-view>
+        </div>
+        <div *ngIf='queryOptimizedLogicalPlan != ""'>
+            <plan-view [jsonPlan]="queryOptimizedLogicalPlan" [plan]="optimalLogicalPlan" [planName]="'OPTIMIZED PLAN'"></plan-view>
+        </div>
+        <div *ngIf='queryLogicalPlan != ""'>
+            <plan-view [jsonPlan]="queryLogicalPlan" [plan]="logicalPlan" [planName]="'LOGICAL PLAN'"></plan-view>
+        </div>
+        </div>
+    </mat-card-content>
 </mat-card>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3e5815a7/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/output.component.scss
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/output.component.scss b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/output.component.scss
index 099ca87..e55a5a5 100755
--- a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/output.component.scss
+++ b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/output.component.scss
@@ -11,159 +11,24 @@ 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.
 */
-$results-spacing-unit: 5px;
 
+$results-spacing-unit: 5px;
 .sql-results-card {
-  display: flex;
-	flex-flow: column;
-  padding: 0;
-  height: 600px;
-  width: 100%; // 1350px;
-	margin: ($results-spacing-unit * 2);
-	min-height: 150px; 
-}
-
-.toolbar-icon {
-  padding: 0 14px 0 0;
-  margin: 0;
-}
-
-.spacer {
-  flex: 1 1 auto;
-}
-
-.results-selector {
-	max-height: 42px;
-  min-height: 42px;
-  justify-content: center;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  overflow: hidden;
-  font-size: 0.80rem;
-  font-weight: 500;
-  background-color: white;
-  border: 1px solid rgba(54, 147, 209, 0.87);
-  overflow-wrap: break-word;
-	word-break: break-all;
+    margin: ($results-spacing-unit);
+    display: flex;
+    flex-flow: column;
+    width: 100%;
+    padding: 0px;
+    border: none !important;
 }
 
 .content-area {
-  position: relative;
-  color: hsla(0,0%,0%,.87);
-  height: 500px;
-  padding: 0;
-  margin: 0;
-  overflow: auto;
-  font-size: 0.80rem;
-  font-weight: 500;
-  font-family: "Roboto", monospace;
-}
-
-.root-closed {
-  list-style-type:none;
-}
-
-.root-open {
-  list-style-type:none;
-}
-
-.leaf-list-open {
-  list-style-type:none;
-  // padding-top: ($results-spacing-unit) * 2;
-  padding-left: 25px;
-  color: red;
-}
-
-.leaf-list-open.div
-//.leaf-list-open.ul
-.leaf-list-open.li {
-  margin-left: ($results-spacing-unit * 10) !important;
-  color: green;
-}
-
-.leaf {
-  color: blue;
-}
-
-.leaf-list-closed {
-  list-style-type:none;
-  display: none;
-}
-
-ul > .root-closed::before {
-  content:'+'
-}
-
-ul > .root-open::before {
-  content:'-'
+    overflow: auto;
+    font-size: 0.80rem;
+    font-weight: 500;
+    font-family: Consolas, monospace;
 }
 
-.queryErrorMessage {
-  border-bottom: 1px solid rgba(0, 0, 0, 0.1);
-  color: rgba(209, 54, 54, 0.87);
-  padding: $results-spacing-unit;
-  padding-left: ($results-spacing-unit * 2);
+.divider {
+    width: 100%;
 }
-
-.metrics {
-  display: flex;
-  color: rgba(54, 147, 209, 0.87);
-  font-size: 0.80rem;
-  font-weight: 500;
-}
-
-.span-results {
-  padding-top: ($results-spacing-unit * 2);
-  padding-left: ($results-spacing-unit * 2);
-}
-
-.actions {
-  border-top: 1px solid rgba(0, 0, 0, 0.1);
-  color: rgba(54, 147, 209, 0.87);
-  margin: 0;
-}
-
-//someID\:review-table
-th {
-  text-align: left !important;
-}
-
-.datatable-header {
-  color: red !important;
-  background-color: blue;
-}
-
-.data-viewer-container {
-  padding: ($results-spacing-unit * 4);
-  padding-bottom: ($results-spacing-unit * 8);
-  height: 100%;
-  overflow: hidden;
-}
-
-.output-group {
-  margin-right: ($results-spacing-unit * 4);
-}
-
-.menu-export {
-  font-size: 0.80rem !important;
-  font-weight: 500 !important;
-}
-
-.button-export {
-  margin-right: ($results-spacing-unit * 4);
-  color: rgba(54, 147, 209, 0.87);
-}
-
-.button-expand {
-  margin-right: ($results-spacing-unit * 4);
-  color: rgba(54, 147, 209, 0.87);
-}
-
-.ui-datatable-data> tr> td {
-  white-space: nowrap;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  max-width: 150px;
-  color: red;
-}
-

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3e5815a7/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/output.component.ts
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/output.component.ts b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/output.component.ts
new file mode 100755
index 0000000..196fbda
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/output.component.ts
@@ -0,0 +1,91 @@
+/*
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+import { Component } from '@angular/core';
+import { Observable } from 'rxjs';
+import { Store } from '@ngrx/store';
+
+@Component({
+    moduleId: module.id,
+    selector: 'awc-results',
+    templateUrl: 'output.component.html',
+    styleUrls: ['output.component.scss']
+})
+
+
+export class QueryOutputComponent {
+    data: any[];
+    currentQueryActive$: Observable < any > ;
+    currentQueryActive: string;
+    queryLogicalPlan = "";
+    queryOptimizedLogicalPlan = "";
+    logicalPlan: any;
+    optimalLogicalPlan: any;
+    results$: Observable < any > ;
+    SQLresults: any;
+    queryId: any = "";
+
+    constructor(private store: Store <any>) {
+        let key = '1';
+        this.currentQueryActive$ = this.store.select(s => s.app.currentQueryIndex);
+        /* this when the editor changes */
+        this.currentQueryActive$.subscribe((data: any) => {
+            if (data) {
+                this.currentQueryActive = data;
+                if (this.SQLresults) {
+                  this.currentQueryActive = data;
+                  this.resultsProccess(this.SQLresults, this.currentQueryActive);
+                }
+            } else {
+                this.currentQueryActive = "0";
+            }
+        })
+        /* this is the output when the quey runs for the first time */
+        this.results$ = this.store.select(s => s.sqlQuery.sqlQueryResultHash);
+        this.results$.subscribe((data: any) => {
+            if (Object.keys(data).length !== 0 && data[this.currentQueryActive]) {
+                this.resultsProccess(data, this.currentQueryActive);
+            } else if (Object.keys(data).length === 0) {
+                this.resultsProccess([], this.currentQueryActive);
+            }
+        })
+    }
+
+    resultsProccess(data: any, queryId) {
+        this.SQLresults = data;
+        this.queryLogicalPlan = "";
+        this.queryOptimizedLogicalPlan = "";
+        if (this.SQLresults[queryId]) {
+            // Extract the logical plan
+            if (this.SQLresults[queryId]['plans']) {
+                if (this.SQLresults[queryId]['plans']['logicalPlan']) {
+                    this.queryLogicalPlan = JSON.stringify(this.SQLresults[queryId]['plans']['logicalPlan'], null, 8);
+                    this.logicalPlan = this.SQLresults[queryId]['plans']['logicalPlan'];
+                }
+                if (this.SQLresults[queryId]['plans']['optimizedLogicalPlan']) {
+                    this.queryOptimizedLogicalPlan = JSON.stringify(this.SQLresults[queryId]['plans']['optimizedLogicalPlan'], null, 8);
+                    this.optimalLogicalPlan = this.SQLresults[queryId]['plans']['optimizedLogicalPlan'];
+                }
+            }
+
+            if (this.SQLresults[queryId]['results'] && this.SQLresults[queryId]['results'].length > 0) {
+                this.data = this.SQLresults[queryId];
+                this.queryId = queryId;
+            } else {
+                this.data = [];
+            }
+        } else {
+              this.data = [];
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3e5815a7/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/plan-node-svg.component.html
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/plan-node-svg.component.html b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/plan-node-svg.component.html
new file mode 100644
index 0000000..1ef741b
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/plan-node-svg.component.html
@@ -0,0 +1,81 @@
+<!--/*
+Licensed 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.
+*/-->
+<svg id='node{{level}}{{item}}{{subplan}}{{planName}}' xmlns="http://www.w3.org/2000/svg" xml:lang="en" xmlns:xlink="http://www.w3.org/1999/xlink"
+  width="200px" height="160px" class="plan-node" (click)="seeDetails(viewParams_)">
+  <title>{{details}}</title>
+  <style>
+    @keyframes cycle {
+      33.3% {
+        visibility: visible;
+      }
+      100% {
+        visibility: hidden
+      }
+    }
+
+    .lit {
+      animation: cycle 9s step-start infinite;
+    }
+
+    .red .lit {
+      animation-delay: -3s;
+    }
+
+    .yellow .lit {
+      animation-delay: -6s;
+    }
+
+    .green .lit {
+      animation-delay: 0;
+    }
+
+    .operation-text {
+      font-size: 12px;
+      font-family: Roboto, "Helvetica Neue", monospace;
+      fill: black;
+    }
+
+    .operation-see-more {
+      font-size: 12px;
+      font-family: Roboto, "Helvetica Neue", monospace;
+      fill: black;
+      cursor: pointer;
+    }
+
+    .card {
+      cursor: pointer;
+    }
+
+    .card:hover {
+      stroke: blue;
+    }
+
+    .operation-details {
+      visibility: none;
+      transition: opacity 1s ease-in-out;
+      opacity: 0;
+    }
+
+  </style>
+  <text class="operation-text" x="50%" y="50%" text-anchor="middle">{{getNodeOperatorId()}} : {{getNodeName()}}</text>
+</svg>
+
+<div class="branch" *ngIf="node.inputs">
+  <li *ngIf="checkSubPlan()" class="li sub">
+    <plan-node-svg class="sub" [planName]="planName" [node]="node.inputs[item].subplan[0]" [level]="0" [item]="0" [subplan]="level+item+subplan+1"></plan-node-svg>
+  </li>
+  <li class="li" *ngFor="let subNode of node.inputs; let i = index">
+    <plan-node-svg class="" [planName]="planName" [node]="subNode" [level]="level+1" [item]="i" [subplan]="subplan" [viewParams]="viewParams"></plan-node-svg>
+  </li>
+</div>

http://git-wip-us.apache.org/repos/asf/asterixdb/blob/3e5815a7/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/plan-node-svg.component.scss
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/plan-node-svg.component.scss b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/plan-node-svg.component.scss
new file mode 100644
index 0000000..f1af051
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/node/src/app/dashboard/query/plan-node-svg.component.scss
@@ -0,0 +1,230 @@
+/*
+Licensed 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.
+*/
+
+//vars
+$page-width: 1000px;
+$padding-base: 12px;
+$padding-sm: 5px;
+$padding-lg: 15px;
+$padding-xl: 25px;
+$font-size-base: 12px;
+$font-size-xs: round($font-size-base * 0.7);
+$font-size-sm: round($font-size-base * 0.9);
+$font-size-lg: round($font-size-base * 1.3);
+$font-size-xl: round($font-size-base * 1.7);
+$font-family-sans-serif: 'noto';
+$font-family-mono: 'source code';
+$line-height-base: 1.3;
+$gray-lightest: #f7f7f7;
+$gray-light: darken($gray-lightest, 10%);
+$gray: darken(#f7f7f7, 30%);
+$gray-dark: darken(#f7f7f7, 50%);
+$gray-darkest: darken($gray-lightest, 70%);
+$blue: #00B5E2;
+$dark-blue: #008CAF;
+$light-blue: #65DDFB;
+$red: #AF2F11;
+$dark-red: #7C210C;
+$light-red: #FB8165;
+$green: #279404;
+$yellow: #F8E400;
+$bg-color: $gray-lightest;
+$text-color: #4d525a;
+$text-color-light: lighten($text-color, 30%);
+$line-color: $gray-light;
+$line-color-light: lighten($gray-light, 10%);
+$link-color: $blue;
+$border-radius-base: 3px;
+$border-radius-lg: 6px;
+$main-color: $blue;
+$main-color-dark: $blue;
+$highlight-color: $blue;
+$highlight-color-dark: $dark-blue;
+$alert-color: #FB4418;
+$connector-height: 20px;
+$connector-line-small: 1px solid darken($line-color, 10%);
+$connector-line-big: 2px solid darken($line-color, 10%);
+.plan-nodea {
+    display: table;
+    position: relative;
+    float: left;
+}
+
+.view-icon {
+    font-size: 14px;
+}
+
+.flex-spacer {
+    flex: 1 1 10%;
+}
+
+.dot {
+    display: flex;
+    flex-flow: column;
+    margin-left: auto;
+    margin-right: auto;
+    padding: 0;
+}
+
+.plan-node {
+    display: flex;
+    flex-flow: column;
+    justify-content: flex-start;
+    color: $text-color;
+    transition: hidden 0.8s;
+    padding: 0px;
+    font-size: 10px;
+    border: 1px solid $line-color;
+    margin: 0px;
+    border-radius: $border-radius-base;
+    width: 200px;
+    height: 60px;
+    box-shadow: 1px 1px 3px 0px rgba(0, 0, 0, 0.1);
+    margin-left: auto;
+    margin-right: auto;
+    padding-left: auto;
+    padding-right: auto;
+    transition: height 0.3s ease-in-out;
+    &:hover {
+        border-color: $highlight-color;
+    }
+}
+
+.plan {
+    list-style: none !important;
+    padding-bottom: $padding-lg * 3;
+    margin-top: 0;
+    padding-top: 0;
+    padding-left: 0;
+
+    .merge {
+        display: flex;
+        flex-flow: column;
+        margin-top: 0 !important;
+        list-style: none;
+        padding-left: 0;
+        color: #00B5E2 !important;
+        border: 1px dashed #00B5E2;
+        justify-content: center;
+        align-items: center;
+    }
+
+    .branch {
+        display: flex;
+        flex-flow: row;
+        margin-top: 0;
+        list-style: none;
+        padding-top: $connector-height;
+        position: relative;
+        transition: all 1s;
+        padding-left: 0;
+        color: black;
+        margin-left: auto;
+        margin-right: auto; // vertical
+        &:before {
+            content: '';
+            position: absolute;
+            top: 0;
+            left: 50%;
+            border-left: $connector-line-small;
+            height: $connector-height;
+            width: 0;
+            color: black;
+            margin-top: 0;
+        }
+        &:first-child {
+            margin-top: 0;
+            &:before {
+                border: none;
+            }
+        }
+        .branch {
+            display: flex;
+            flex-flow: row;
+            margin-top: 0 !important;
+            list-style: none;
+            padding-left: 0;
+        }
+
+        li {
+            display: inline;
+            list-style-type: none;
+            position: relative;
+            padding: $connector-height $padding-sm 0 $padding-sm;
+            transition: all 1s;
+            margin-left: auto;
+            margin-right: auto; // connectors
+            &:before,
+            &:after {
+                content: '';
+                position: absolute;
+                top: 0;
+                right: 50%;
+                border-top: $connector-line-small;
+                width: 50%;
+                height: $connector-height;
+            }
+            &:after {
+                right: auto;
+                left: 50%;
+                border-left: $connector-line-small;
+            }
+            &:only-child {
+                padding-top: 0;
+                &:after,
+                &:before {
+                display: none;
+                }
+            }
+            &:first-child::before,
+            &:last-child::after {
+                border: 0 none;
+            }
+            &:last-child::before {
+                border-right: $connector-line-small;
+                border-radius: 0 $border-radius-lg 0 0;
+            }
+            &:first-child::after {
+                border-radius: $border-radius-lg 0 0 0;
+            }
+        }
+    }
+}
+
+.sub {
+    .plan-node {
+        background-color: rgb(230, 230, 230);
+    }
+}
+
+.viewMe {
+    display: inline-block;
+    position: relative;
+    cursor: pointer;
+}
+
+.node-summary {
+    display: block;
+    margin: 10px 0 10px 0;
+    text-align: left;
+}
+
+.node-details {
+    display: block;
+    text-align: left;
+}
+
+.node-subplan {
+    float: right;
+}
\ No newline at end of file