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/01/08 18:07:06 UTC
[10/21] asterixdb git commit: [ASTERIXDB-2222][UI] Move dashboard to
own module
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/datasets.component.ts
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/datasets.component.ts b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/datasets.component.ts
new file mode 100755
index 0000000..0fe8c74
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/datasets.component.ts
@@ -0,0 +1,231 @@
+/*
+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, ElementRef, ViewChild, Inject, Input } from '@angular/core';
+import { Dataset } from '../../../shared/models/asterixDB.model'
+import { Store } from '@ngrx/store';
+import { Observable } from 'rxjs/Observable';
+import * as datasetActions from '../../../shared/actions/dataset.actions'
+import {DataSource} from '@angular/cdk/collections';
+import {BehaviorSubject} from 'rxjs/BehaviorSubject';
+import { Subscription } from "rxjs/Rx";
+import { State } from '../../../shared/reducers/dataset.reducer';
+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 { MatPaginator } from '@angular/material';
+import { SelectionModel } from '@angular/cdk/collections';
+import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
+
+/**
+ * Root component
+ * Defines our application's layout
+ */
+@Component({
+ selector: 'awc-datasets',
+ templateUrl: 'datasets.component.html',
+ styleUrls: ['datasets.component.scss']
+})
+
+export class DatasetCollection {
+ displayedColumns = "['CompactionPolicy', 'DatasetId', 'DatasetName', 'DatasetType', 'DatatypeDataverseName', 'DatatypeName', 'DataverseName', 'GroupName', 'PendingOp', 'Timestamp']"
+
+/*
+ compactionPolicy: string;
+ compactionPolicyProperties: CompactionPolicyProperties[]; *
+ datasetId: string;
+ datasetName: string;
+ datasetType:string;
+ datatypeDataverseName: string;
+ datatypeName: string;
+ dataverseName: string;
+ groupName:string;
+ hints: string[]; *
+ internalDetails: InternalDetails; *
+ pendingOp: string;
+ timestamp: string; */
+ datasetName: string;
+ dataSource: DatasetDataSource | null;
+ loaded$: Observable<any>
+ @Input('message') errorMessage: string = ""
+ dsName = "";
+
+ constructor(private store: Store<any>, public dialog: MatDialog) {
+ this.loaded$ = this.store.select('dataset');
+
+ // Watching the name of the latest create dataset
+ this.store.select(s => s.dataset.createDatasetName).subscribe((data: any) => {
+ this.dsName = data;
+ })
+
+ // Watching the name of the latest drop dataset
+ this.store.select(s => s.dataset.dropDatasetName).subscribe((data: any) => {
+ this.dsName = data;
+ })
+
+ // Watching for the if there is a change in the collection
+ this.store.select(s => s.dataset.createDatasetSuccess).subscribe((data: any) => {
+ if (data === true) {
+ this.getDatasets();
+ this.errorMessage = "SUCCEED: CREATE DATASET " + this.dsName;
+ }
+ })
+
+ // Watching for the if there is a error in a create dataset operation
+ this.store.select(s => s.dataset.createDatasetError).subscribe((data: any) => {
+ if (data.errors) {
+ this.errorMessage = "ERROR: " + data.errors[0].msg;
+ }
+ })
+
+
+ // Watching for the success message in a drop dataset operation
+ this.store.select(s => s.dataset.dropDatasetSuccess).subscribe((data: any) => {
+ if (data === true) {
+ this.getDatasets();
+ this.errorMessage = "SUCCEED: DROP DATASET " + this.dsName;
+ }
+ })
+
+ // Watching for the if there is a error in a drop dataset operation
+ this.store.select(s => s.dataset.dropDatasetError).subscribe((data: any) => {
+ if (data.errors) {
+ this.errorMessage = "ERROR: " + data.errors[0].msg;
+ }
+ })
+ }
+
+ getDatasets() {
+ // Trigger the effect to refresh the dataset
+ this.store.dispatch(new datasetActions.SelectDatasets('-'));
+ }
+
+ ngOnInit() {
+ // Assign the datasource for the table
+ this.dataSource = new DatasetDataSource(this.store);
+ }
+
+ /*
+ * opens the create dataverse dialog
+ */
+ openCreateDatasetDialog(): void {
+ let dialogRef = this.dialog.open(DialogCreateDataset, {
+ width: '420px',
+ data: { name: this.datasetName }
+ });
+
+ dialogRef.afterClosed().subscribe(result => {
+ this.datasetName = result;
+ });
+ }
+
+ /*
+ * opens the drop dataverse dialog
+ */
+ openDropDatasetDialog(): void {
+ let dialogRef = this.dialog.open(DialogDropDataset, {
+ width: '420px',
+ data: { name: this.datasetName }
+ });
+
+ dialogRef.afterClosed().subscribe(result => {
+ this.datasetName = result;
+ });
+ }
+
+ /*
+ * Clean up the error message on the screen
+ */
+ onClick(): void {
+ this.errorMessage = "";
+ }
+
+ output: any;
+
+ highlight(row){
+ this.output = JSON.stringify(row, null, 2);
+ }
+
+ @ViewChild('querymetadata') inputQuery;
+
+ /* Cleans up error message */
+ cleanUp() {
+ this.errorMessage = "";
+ // Cascading
+ this.inputQuery.cleanUp();
+ }
+}
+
+@Component({
+ selector: 'dataset-create-dialog',
+ templateUrl: 'dataset-create-dialog.component.html',
+ styleUrls: ['dataset-create-dialog.component.scss']
+})
+
+export class DialogCreateDataset {
+ constructor( private store: Store<any>,
+ public dialogCreateDsRef: MatDialogRef<DialogCreateDataset>,
+ @Inject(MAT_DIALOG_DATA) public data: any) { }
+
+ onClick(): void {
+ this.store.dispatch(new datasetActions.CreateDataset(this.data.datasetName));
+ this.dialogCreateDsRef.close();
+ }
+
+ onNoClick(): void {
+ this.dialogCreateDsRef.close();
+ }
+}
+
+@Component({
+ selector: 'dataset-drop-dialog',
+ templateUrl: 'dataset-drop-dialog.component.html',
+ styleUrls: ['dataset-drop-dialog.component.scss']
+})
+
+export class DialogDropDataset {
+ constructor( private store: Store<any>,
+ public dialogDropDsRef: MatDialogRef<DialogDropDataset>,
+ @Inject(MAT_DIALOG_DATA) public data: any) { }
+
+ onClick(): void {
+ this.store.dispatch(new datasetActions.DropDataset(this.data.datasetName));
+ this.dialogDropDsRef.close();
+ }
+
+ onNoClick(): void {
+ this.dialogDropDsRef.close();
+ }
+}
+
+export class DatasetDataSource extends DataSource<any> {
+ private datasets$: Observable<any>
+ constructor(private store: Store<any>) {
+ super();
+ this.datasets$ = this.store.select(s => s.dataset.datasets.results);
+ }
+
+ /** Connect function called by the table to retrieve one stream containing the data to render. */
+ connect(): Observable<Dataset[]> {
+ const displayDataChanges = [
+ this.datasets$,
+ ];
+
+ return this.datasets$;
+ }
+
+ disconnect() {}
+}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-create-dialog.component.html
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-create-dialog.component.html b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-create-dialog.component.html
new file mode 100755
index 0000000..aca06fd
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-create-dialog.component.html
@@ -0,0 +1,14 @@
+<!--/*
+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 -->
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-create-dialog.component.scss
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-create-dialog.component.scss b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-create-dialog.component.scss
new file mode 100755
index 0000000..9502a7e
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-create-dialog.component.scss
@@ -0,0 +1,18 @@
+/*
+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.
+*/
+.datatype-dialog {
+ font-family: "Roboto Mono", monospace;
+ font-size: 0.80rem;
+ font-weight: 500;
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-drop-dialog.component.html
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-drop-dialog.component.html b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-drop-dialog.component.html
new file mode 100755
index 0000000..1157261
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-drop-dialog.component.html
@@ -0,0 +1,26 @@
+<!--/*
+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="datatype-dialog">
+ <p mat-dialog-title>DROP DATATYPE</p>
+ <mat-dialog-content>
+ <p>PLEASE GIVE THE NAME OF THE DATATYPE TO DROP</p>
+ </mat-dialog-content>
+ <mat-form-field>
+ <input matInput tabindex="0" [(ngModel)]="data.datatypeName">
+ </mat-form-field>
+ <mat-dialog-actions>
+ <button mat-button (click)="onClick()" tabindex="1">DROP</button>
+ <button mat-button (click)="onNoClick()" tabindex="2">CANCEL</button>
+ </mat-dialog-actions>
+</div>
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-drop-dialog.component.scss
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-drop-dialog.component.scss b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-drop-dialog.component.scss
new file mode 100755
index 0000000..9502a7e
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-drop-dialog.component.scss
@@ -0,0 +1,18 @@
+/*
+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.
+*/
+.datatype-dialog {
+ font-family: "Roboto Mono", monospace;
+ font-size: 0.80rem;
+ font-weight: 500;
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatypes.component.html
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatypes.component.html b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatypes.component.html
new file mode 100755
index 0000000..e580a54
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatypes.component.html
@@ -0,0 +1,70 @@
+<!--/*
+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="container" (click)="onClick()">
+ <div class="master">
+ <mat-card class="datatypes-card" *ngIf="loaded$ | async as ld">
+ <mat-toolbar color="primary" class="datatypes-selector">
+ <mat-icon class="icon">menu</mat-icon>
+ <span>DATATYPES - METADATA</span>
+ <span class="spacer"></span>
+ </mat-toolbar>
+ <mat-card-content class="datatypes-content">
+ <mat-table #table [dataSource]="dataSource" class="datatypes-table" role="treegrid">
+ <!-- Datatype Name -->
+ <ng-container matColumnDef="DatatypeName">
+ <mat-header-cell *matHeaderCellDef class="header-datatypename-cell">Datatype Name</mat-header-cell>
+ <mat-cell *matCellDef="let element" class="datatypes-datatypename-cell">{{element.DatatypeName}} </mat-cell>
+ </ng-container>
+
+ <!-- Data Type Dataverse Name -->
+ <ng-container matColumnDef="DataverseName">
+ <mat-header-cell *matHeaderCellDef class="header-dataversename-cell">Dataverse Name </mat-header-cell>
+ <mat-cell *matCellDef="let element" class="datatypes-dataversename-cell">{{element.DataverseName}} </mat-cell>
+ </ng-container>
+
+ <!-- Timestamp Column -->
+ <ng-container matColumnDef="Timestamp">
+ <mat-header-cell *matHeaderCellDef class="header-timestamp-cell">Timestamp</mat-header-cell>
+ <mat-cell *matCellDef="let element" class="datatypes-timestamp-cell">{{element.Timestamp}}</mat-cell>
+ </ng-container>
+
+ <mat-header-row *matHeaderRowDef="['DatatypeName', 'DataverseName', 'Timestamp']"></mat-header-row>
+ <mat-row *matRowDef="let row; columns: ['DatatypeName', 'DataverseName', 'Timestamp'];"
+ [ngClass]="{'highlight': selectedRowIndex == row.id}"
+ (click)="highlight(row)">
+ </mat-row>
+ </mat-table>
+ </mat-card-content>
+ <mat-card-actions class="actions">
+ <button class="refresh-button" mat-button (click)="openDropDatatypeDialog()">DROP</button>
+ <span class="error-message">{{errorMessage}}</span>
+ <span class="spacer"></span>
+ <button class="refresh-button" mat-button (click)="getDatatypes()">REFRESH</button>
+ </mat-card-actions>
+ </mat-card>
+ <awc-query-metadata #querymetadata class="query"></awc-query-metadata>
+ </div>
+ <div class="detail">
+ <mat-card class="datatypes-details-card">
+ <mat-toolbar color="primary" class="datatypes-selector">
+ <mat-icon class="icon">menu</mat-icon>
+ <span>DATATYPE - METADATA - DETAILS</span>
+ <span class="spacer"></span>
+ </mat-toolbar>
+ <mat-card-content class="datatypes-content output">
+ <span><pre>{{output}}</pre></span>
+ </mat-card-content>
+ </mat-card>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatypes.component.scss
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatypes.component.scss b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatypes.component.scss
new file mode 100755
index 0000000..d4aeffc
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatypes.component.scss
@@ -0,0 +1,267 @@
+/*
+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.
+*/
+$datatypes-spacing-unit: 8px;
+
+.container {
+ display: flex;
+ flex-flow: row;
+ padding: 0;
+ margin: 0;
+}
+
+.master {
+ width: 60%;
+ overflow: hidden;
+}
+
+.detail {
+ width: 40%;
+ overflow: hidden;
+}
+
+.datatypes-card {
+ display: flex;
+ flex-flow: column;
+ padding: 0;
+ margin:0 auto;
+ margin-top: ($datatypes-spacing-unit * 2);
+ min-height: 450px;
+ max-height: 450px;
+ //min-width: 98%; //(100vw / 2);
+ //max-width: 98%; // (100vw / 2);
+ width: 95%; // 98%;
+ overflow: hidden;
+}
+
+.datatypes-details-card {
+ display: flex;
+ flex-flow: column;
+ padding: 0;
+ margin:0 auto;
+ margin: ($datatypes-spacing-unit * 2);
+ min-height: 716px;
+ max-height: 716px;
+ //min-width: 95%; //(100vw / 2);
+ //max-width: 95%; // (100vw / 2);
+ overflow: hidden;
+}
+
+.icon {
+ padding: 0 14px 0 0;
+ margin: 0;
+}
+
+.spacer {
+ flex: 1 1 auto;
+}
+
+.datatypes-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);
+}
+
+.datatypes-content {
+ position:relative;
+ top: 0;
+ left: 0;
+ margin: 0px;
+ padding: 0px;
+ overflow: auto;
+}
+
+.datatypes-table {
+ margin: $datatypes-spacing-unit !important;
+ height: 330px;
+ overflow: auto;
+}
+
+.spacer {
+ flex: 1 1 auto;
+}
+
+.datatypes-toolbar {
+ display: block;
+ min-height: 56px;
+ height: 56px;
+// width: 250px;
+ font-size: 12px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ letter-spacing: 1px;
+ font-weight: 400;
+ background: rgba(0,0,1, .80);
+}
+
+.example-header {
+ min-height: 64px;
+ display: flex;
+ align-items: center;
+ padding-left: 24px;
+ font-size: 20px;
+}
+
+.mat-table {
+ overflow: auto;
+}
+
+.customWidthClass{
+ flex: 0 0 75px;
+}
+
+.mat-column-DataverseName {
+ text-align: left;
+}
+
+.mat-header-cell.mat-column-DataverseName {
+ text-align: left;
+}
+
+.mat-cell.mat-column-DataverseName {
+ text-align: left;
+}
+
+.header-datatypename-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $datatypes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($datatypes-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ text-transform: uppercase;
+ flex: 0 0 400px;
+}
+
+.datatypes-datatypename-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $datatypes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($datatypes-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ flex: 0 0 400px;
+}
+
+.header-dataversename-cell {
+ display: flex;
+ justify-content: center;
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $datatypes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($datatypes-spacing-unit * 2);
+ text-align: center;
+ color: hsla(0,0%,0%,.87);
+ text-transform: uppercase;
+ flex: 0 0 250px;
+}
+
+.datatypes-dataversename-cell {
+ display: flex;
+ justify-content: center;
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $datatypes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($datatypes-spacing-unit * 2);
+ flex: 0 0 250px;
+}
+
+.header-timestamp-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $datatypes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($datatypes-spacing-unit * 2);
+ text-align: center;
+ color: hsla(0,0%,0%,.87);
+ text-transform: uppercase;
+ flex: 0 0 250px;
+}
+
+.datatypes-timestamp-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $datatypes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($datatypes-spacing-unit * 2);
+ text-align: center;
+ color: hsla(0,0%,0%,.87);
+ flex: 0 0 250px;
+}
+
+.example-header {
+ min-height: 56px;
+ max-height: 56px;
+ display: flex;
+ align-items: center;
+ padding: 8px 24px 0;
+ font-size: 20px;
+ justify-content: space-between;
+ border-bottom: 1px solid transparent;
+}
+
+.mat-form-field {
+ font-size: 14px;
+ flex-grow: 1;
+ margin-top: 8px;
+}
+
+.example-no-results {
+ display: flex;
+ justify-content: center;
+ padding: 24px;
+ font-size: 12px;
+ font-style: italic;
+}
+
+.actions {
+ display: flex;
+ border-top: 1px solid rgba(0, 0, 0, 0.1);
+ color: rgba(54, 147, 209, 0.87);
+ padding: $datatypes-spacing-unit;
+ margin: 0;
+}
+
+.error-message {
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+ color: rgba(209, 54, 54, 0.87);
+ padding-top: 10px;
+ padding-left: 20px;
+ text-overflow: ellipsis;
+}
+
+.output {
+ padding-left: ($datatypes-spacing-unit * 2);
+}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatypes.component.ts
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatypes.component.ts b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatypes.component.ts
new file mode 100755
index 0000000..953a27e
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatypes.component.ts
@@ -0,0 +1,220 @@
+/*
+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, ChangeDetectionStrategy, Inject, Input } from '@angular/core';
+import { Datatype } from '../../../shared/models/asterixDB.model'
+import { Store } from '@ngrx/store';
+import { Observable } from 'rxjs/Observable';
+import * as datatypeActions from '../../../shared/actions/datatype.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 { State } from '../../../shared/reducers/datatype.reducer';
+import { MatPaginator } from '@angular/material';
+import { SelectionModel } from '@angular/cdk/collections';
+import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
+
+@Component({
+ selector: 'awc-datatypes',
+ templateUrl: 'datatypes.component.html',
+ styleUrls: ['datatypes.component.scss']
+})
+
+export class DatatypeCollection {
+ displayedColumns = "['datatypeName', 'dataverseName', 'timeStamp']"
+ /*
+ datatypeName: string;
+ dataverseName: string;
+ derived: DatatypeDerived;
+ timeStamp: string;
+ */
+ datatypeName: string;
+ dataSource: DatatypeDataSource | null;
+ loaded$: Observable<any>;
+ @ViewChild(MatPaginator) paginator: MatPaginator;
+ @ViewChild('filter') filter: ElementRef;
+ selection = new SelectionModel<string>(true, []);
+ @Input('message') errorMessage: string = ""
+ dtName = "";
+
+ constructor(private store: Store<any>, public dialog: MatDialog) {
+ this.loaded$ = this.store.select('datatype');
+ // Watching the name of the latest create datatype
+ this.store.select(s => s.datatype.createDatatypeName).subscribe((data: any) => {
+ this.dtName = data;
+ })
+
+ // Watching the name of the latest drop datatype
+ this.store.select(s => s.datatype.dropDatatypeName).subscribe((data: any) => {
+ this.dtName = data;
+ })
+
+ // Watching for the if there is a change in the collection
+ this.store.select(s => s.datatype.createDatatypeSuccess).subscribe((data: any) => {
+ if (data === true) {
+ this.getDatatypes();
+ this.errorMessage = "SUCCEED: CREATE DATATYPE " + this.dtName;
+ }
+ })
+
+ // Watching for the if there is a error in a create datatype operation
+ this.store.select(s => s.datatype.createDatatypeError).subscribe((data: any) => {
+ if (data.errors) {
+ this.errorMessage = "ERROR: " + data.errors[0].msg;
+ }
+ })
+
+ // Watching for the success message in a drop datatype operation
+ this.store.select(s => s.datatype.dropDatatypeSuccess).subscribe((data: any) => {
+ if (data === true) {
+ this.getDatatypes();
+ this.errorMessage = "SUCCEED: DROP DATATYPE " + this.dtName;
+ }
+ })
+
+ // Watching for the if there is a error in a drop datatype operation
+ this.store.select(s => s.datatype.dropDatatypeError).subscribe((data: any) => {
+ if (data.errors) {
+ this.errorMessage = "ERROR: " + data.errors[0].msg;
+ }
+ })
+ }
+
+ getDatatypes() {
+ // Triggers the effect to refresg the datatypes
+ this.store.dispatch(new datatypeActions.SelectDatatypes('-'));
+ }
+
+ ngOnInit() {
+ // Assign the datasource for the table
+ this.dataSource = new DatatypeDataSource(this.store);
+ }
+
+ /*
+ * opens the create datatype dialog
+ */
+ openCreateDatatypeDialog(): void {
+ let dialogRef = this.dialog.open(DialogCreateDatatype, {
+ width: '420px',
+ data: { name: this.datatypeName }
+ });
+
+ dialogRef.afterClosed().subscribe(result => {
+ this.datatypeName = result;
+ });
+ }
+
+ /*
+ * opens the drop datatype dialog
+ */
+ openDropDatatypeDialog(): void {
+ let dialogRef = this.dialog.open(DialogDropDatatype, {
+ width: '420px',
+ data: { name: this.datatypeName }
+ });
+
+ dialogRef.afterClosed().subscribe(result => {
+ this.datatypeName = result;
+ });
+ }
+
+ onClick(): void {
+ this.errorMessage = "";
+ }
+
+ /* Showing all the datatype metadata information */
+ output: any;
+
+ highlight(row){
+ this.output = JSON.stringify(row, null, 2);
+ }
+
+ @ViewChild('querymetadata') inputQuery;
+
+ /* Cleans up error message */
+ cleanUp() {
+ this.errorMessage = "";
+ // Cascading
+ this.inputQuery.cleanUp();
+ }
+}
+
+@Component({
+ selector: 'datatype-create-dialog',
+ templateUrl: 'datatype-create-dialog.component.html',
+ styleUrls: ['datatype-create-dialog.component.scss']
+})
+
+export class DialogCreateDatatype {
+ constructor( private store: Store<any>,
+ public dialogCreateDtRef: MatDialogRef<DialogCreateDatatype>,
+ @Inject(MAT_DIALOG_DATA) public data: any) { }
+
+ onClick(): void {
+ this.store.dispatch(new datatypeActions.CreateDatatype(this.data.datasetName));
+ this.dialogCreateDtRef.close();
+ }
+
+ onNoClick(): void {
+ this.dialogCreateDtRef.close();
+ }
+}
+
+@Component({
+ selector: 'datatypes-drop-dialog',
+ templateUrl: 'datatype-drop-dialog.component.html',
+ styleUrls: ['datatype-drop-dialog.component.scss']
+})
+
+export class DialogDropDatatype {
+ constructor( private store: Store<any>,
+ public dialogDropDtRef: MatDialogRef<DialogDropDatatype>,
+ @Inject(MAT_DIALOG_DATA) public data: any) { }
+
+ onClick(): void {
+ this.store.dispatch(new datatypeActions.DropDatatype(this.data.datatypeName));
+ this.dialogDropDtRef.close();
+ }
+
+ onNoClick(): void {
+ this.dialogDropDtRef.close();
+ }
+}
+
+export class DatatypeDataSource extends DataSource<any> {
+ private datatypes$: Observable<any>
+
+ constructor(private store: Store<any>) {
+ super();
+ this.datatypes$ = this.store.select(s => s.datatype.datatypes.results);
+ }
+
+ /** Connect function called by the table to retrieve one stream containing the data to render. */
+ connect(): Observable<Datatype[]> {
+ const displayDataChanges = [
+ this.datatypes$,
+ // this._filterChange,
+ ];
+
+ return this.datatypes$;
+ }
+
+ disconnect() {}
+}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-create-dialog.component.html
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-create-dialog.component.html b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-create-dialog.component.html
new file mode 100755
index 0000000..5159e38
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-create-dialog.component.html
@@ -0,0 +1,27 @@
+<!--/*
+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="dataverse-dialog">
+ <p mat-dialog-title>CREATE DATAVERSE</p>
+ <mat-dialog-content>
+ <p>GIVE A NAME TO THE NEW DATAVERSE</p>
+ </mat-dialog-content>
+ <mat-form-field>
+ <input matInput tabindex="0" [(ngModel)]="data.dataverseName">
+ </mat-form-field>
+ </div>
+ <div mat-dialog-actions>
+ <button mat-button [mat-dialog-close]="data.dataverseName" (click)="onClick()" tabindex="1">CREATE</button>
+ <button mat-button (click)="onNoClick()" tabindex="2">CANCEL</button>
+</div>
+
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-create-dialog.component.scss
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-create-dialog.component.scss b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-create-dialog.component.scss
new file mode 100755
index 0000000..6371068
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-create-dialog.component.scss
@@ -0,0 +1,18 @@
+/*
+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.
+*/
+.dataverse-dialog {
+ font-family: "Roboto Mono", monospace;
+ font-size: 0.80rem;
+ font-weight: 500;
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-drop-dialog.component.html
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-drop-dialog.component.html b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-drop-dialog.component.html
new file mode 100755
index 0000000..b546a70
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-drop-dialog.component.html
@@ -0,0 +1,26 @@
+<!--/*
+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="dataverse-dialog">
+ <p mat-dialog-title>DROP DATAVERSE</p>
+ <mat-dialog-content>
+ <p>PLEASE GIVE THE NAME OF THE DATAVERSE TO DROP</p>
+ </mat-dialog-content>
+ <mat-form-field>
+ <input matInput tabindex="0" [(ngModel)]="data.dataverseName">
+ </mat-form-field>
+ <mat-dialog-actions>
+ <button mat-button (click)="onClick()" tabindex="1">DROP</button>
+ <button mat-button (click)="onNoClick()" tabindex="2">CANCEL</button>
+ </mat-dialog-actions>
+</div>
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-drop-dialog.component.scss
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-drop-dialog.component.scss b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-drop-dialog.component.scss
new file mode 100755
index 0000000..6371068
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-drop-dialog.component.scss
@@ -0,0 +1,18 @@
+/*
+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.
+*/
+.dataverse-dialog {
+ font-family: "Roboto Mono", monospace;
+ font-size: 0.80rem;
+ font-weight: 500;
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses.component.html
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses.component.html b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses.component.html
new file mode 100755
index 0000000..4099704
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses.component.html
@@ -0,0 +1,77 @@
+<!--/*
+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="container" (click)="onClick()">
+ <div class="master">
+ <mat-card class="dataverses-card">
+ <mat-toolbar color="primary" class="dataverses-selector">
+ <mat-icon class="icon">menu</mat-icon>
+ <span>DATAVERSES - METADATA</span>
+ <span class="spacer"></span>
+ </mat-toolbar>
+ <mat-card-content class="dataverses-content">
+ <mat-table #table [dataSource]="dataSource" class="dataverses-table" *ngIf="loaded$ | async as ld">
+ <!-- Dataverse Name Column -->
+ <ng-container matColumnDef="DataverseName">
+ <mat-header-cell *matHeaderCellDef class="header-name-cell">Dataverse Name</mat-header-cell>
+ <mat-cell *matCellDef="let element" class="dataverse-name-cell">{{element.DataverseName}}</mat-cell>
+ </ng-container>
+
+ <!-- Data Format Column -->
+ <ng-container matColumnDef="DataFormat">
+ <mat-header-cell *matHeaderCellDef class="header-dataformat-cell">Data Format</mat-header-cell>
+ <mat-cell *matCellDef="let element" class="dataverse-dataformat-cell">{{element.DataFormat}}</mat-cell>
+ </ng-container>
+
+ <!-- Pending Ops -->
+ <ng-container matColumnDef="PendingOp">
+ <mat-header-cell *matHeaderCellDef class="header-pendingop-cell">Pending Ops</mat-header-cell>
+ <mat-cell *matCellDef="let element" class="dataverse-pendingop-cell">{{element.PendingOp}}</mat-cell>
+ </ng-container>
+
+ <!-- Timestamp Column -->
+ <ng-container matColumnDef="Timestamp">
+ <mat-header-cell *matHeaderCellDef class="header-timestamp-cell">Timestamp</mat-header-cell>
+ <mat-cell *matCellDef="let element" class="dataverse-timestamp-cell">{{element.Timestamp}}</mat-cell>
+ </ng-container>
+
+ <mat-header-row *matHeaderRowDef="['DataverseName', 'DataFormat', 'Timestamp']"></mat-header-row>
+ <mat-row *matRowDef="let row; columns: ['DataverseName', 'DataFormat', 'Timestamp'];"
+ [ngClass]="{'highlight': selectedRowIndex == row.id}"
+ (click)="highlight(row)">
+ </mat-row>
+ </mat-table>
+ </mat-card-content>
+ <mat-card-actions class="actions">
+ <button class="refresh-button" mat-button (click)="openCreateDataverseDialog()">CREATE</button>
+ <button class="refresh-button" mat-button (click)="openDropDataverseDialog()">DROP</button>
+ <span class="error-message">{{errorMessage}}</span>
+ <span class="spacer"></span>
+ <button class="refresh-button" mat-button (click)="getDataverse()">REFRESH</button>
+ </mat-card-actions>
+ </mat-card>
+ <awc-query-metadata #querymetadata class="query"></awc-query-metadata>
+ </div>
+ <div class="detail">
+ <mat-card class="dataverses-details-card">
+ <mat-toolbar color="primary" class="dataverses-selector">
+ <mat-icon class="icon">menu</mat-icon>
+ <span>DATAVERSE - METADATA - DETAILS</span>
+ <span class="spacer"></span>
+ </mat-toolbar>
+ <mat-card-content class="dataverses-content output">
+ <span><pre>{{output}}</pre></span>
+ </mat-card-content>
+ </mat-card>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses.component.scss
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses.component.scss b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses.component.scss
new file mode 100755
index 0000000..2821766
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses.component.scss
@@ -0,0 +1,259 @@
+/*
+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.
+*/
+$dataverses-spacing-unit: 8px;
+
+.container {
+ display: flex;
+ flex-flow: row;
+ padding: 0;
+ margin: 0;
+}
+
+.master {
+ width: 60%;
+}
+
+.detail {
+ width: 40%;
+}
+
+.dataverses-card {
+ display: flex;
+ flex-flow: column;
+ padding: 0;
+ margin:0 auto;
+ margin-top: ($dataverses-spacing-unit * 2);
+ min-height: 450px;
+ max-height: 450px;
+ //min-width: 98%; //(100vw / 2);
+ //max-width: 98%; // (100vw / 2);
+ width: 95%; // 98%;
+ overflow: hidden;
+}
+
+.dataverses-details-card {
+ display: flex;
+ flex-flow: column;
+ padding: 0;
+ margin:0 auto;
+ margin: ($dataverses-spacing-unit * 2);
+ min-height: 716px;
+ max-height: 716px;
+ //min-width: 95%; //(100vw / 2);
+ //max-width: 95%; // (100vw / 2);
+ overflow: hidden;
+}
+
+.icon {
+ padding: 0 14px 0 0;
+ margin: 0;
+}
+
+.spacer {
+ flex: 1 1 auto;
+}
+
+.dataverses-selector {
+ min-height: 42px;
+ max-height: 42px;
+ justify-content: center;
+ font-size: 0.80rem;
+ font-weight: 500;
+ background-color: white;
+ border: 1px solid rgba(54, 147, 209, 0.87);
+}
+
+//.metadata-content-area {
+// padding: ($dataverses-spacing-unit * 2);
+// margin: 0;
+// overflow: auto;
+//}
+
+
+.dataverses-content {
+ position:relative;
+ top: 0;
+ left: 0;
+ margin: 0px;
+ padding: 0px;
+ overflow: auto;
+}
+
+.dataverses-table {
+ margin: $dataverses-spacing-unit !important;
+ height: 330px;
+ overflow: auto;
+}
+
+.spacer {
+ flex: 1 1 auto;
+}
+
+.example-header {
+ min-height: 64px;
+ display: flex;
+ align-items: center;
+ padding-left: 24px;
+ font-size: 20px;
+}
+
+.mat-table {
+ overflow: auto;
+}
+
+.customWidthClass{
+ flex: 0 0 75px;
+}
+
+.mat-column-DataverseName {
+ text-align: left;
+}
+
+.mat-header-cell.mat-column-DataverseName {
+ text-align: left;
+}
+
+.mat-cell.mat-column-DataverseName {
+ text-align: left;
+}
+
+.header-name-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $dataverses-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($dataverses-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ flex: 0 0 150px;
+ text-transform: uppercase;
+}
+
+.header-dataformat-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $dataverses-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($dataverses-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ flex: 0 0 400px;
+ text-transform: uppercase;
+}
+
+.header-timestamp-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $dataverses-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($dataverses-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ flex: 0 0 250px;
+ text-transform: uppercase;
+}
+
+.dataverse-name-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $dataverses-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($dataverses-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ flex: 0 0 150px;
+}
+
+.dataverse-dataformat-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $dataverses-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($dataverses-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ flex: 0 0 400px;
+}
+
+.dataverse-timestamp-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $dataverses-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($dataverses-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ flex: 0 0 250px;
+}
+
+.example-header {
+ min-height: 56px;
+ max-height: 56px;
+ display: flex;
+ align-items: center;
+ padding: 8px 24px 0;
+ font-size: 20px;
+ justify-content: space-between;
+ border-bottom: 1px solid transparent;
+}
+
+.mat-form-field {
+ font-size: 14px;
+ flex-grow: 1;
+ margin-top: 8px;
+}
+
+.example-no-results {
+ display: flex;
+ justify-content: center;
+ padding: 24px;
+ font-size: 12px;
+ font-style: italic;
+}
+
+.actions {
+ display: flex;
+ border-top: 1px solid rgba(0, 0, 0, 0.1);
+ color: rgba(54, 147, 209, 0.87);
+ padding: $dataverses-spacing-unit;
+ margin: 0;
+}
+
+.error-message {
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+ color: rgba(209, 54, 54, 0.87);
+ padding-top: 10px;
+ padding-left: 20px;
+ text-overflow: ellipsis;
+}
+
+.highlight{
+ background: #42A948; /* green */
+}
+
+.output {
+ padding-left: ($dataverses-spacing-unit * 2);
+}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses.component.ts
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses.component.ts b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses.component.ts
new file mode 100755
index 0000000..981f029
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses.component.ts
@@ -0,0 +1,234 @@
+/*
+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, ChangeDetectionStrategy, Inject, OnInit, AfterViewChecked, AfterViewInit, Input} from '@angular/core';
+import { Dataverse } from '../../../shared/models/asterixDB.model'
+import { Store } from '@ngrx/store';
+import { Observable } from 'rxjs/Observable';
+import * as dataverseActions from '../../../shared/actions/dataverse.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 { MatPaginator } from '@angular/material';
+import { SelectionModel } from '@angular/cdk/collections';
+import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
+
+@Component({
+ selector: 'awc-dataverses',
+ templateUrl: 'dataverses.component.html',
+ styleUrls: ['dataverses.component.scss'],
+})
+
+export class DataverseCollection implements OnInit, AfterViewChecked, AfterViewInit {
+ dataverseName: string;
+ displayedColumns = ['DataverseName', 'Dataformat', 'Timestamp', 'PendingOp'];
+ dataSource: DataversesDataSource | null;
+ loaded$: Observable<any>;
+ selection = new SelectionModel<string>(true, []);
+ @Input('message') errorMessage: string = ""
+ dvName = "";
+
+ constructor(private store: Store<any>, public dialog: MatDialog) {
+ this.loaded$ = this.store.select('dataverse');
+
+ // Watching the name of the latest created dataset
+ this.store.select(s => s.dataverse.createDataverseName).subscribe((data: any) => {
+ this.dvName = data;
+ })
+
+ // Watching for the success message in a drop dataset operation
+ this.store.select(s => s.dataverse.dropDataverseName).subscribe((data: any) => {
+ this.dvName = data;
+ })
+
+ // Watching for the if there is a change in the collection
+ this.store.select(s => s.dataverse.createDataverseSuccess).subscribe((data: any) => {
+ if (data === true) {
+ this.getDataverse();
+ this.errorMessage = "SUCCEED: CREATED DATAVERSE " + this.dvName + " ";
+ }
+ })
+
+ // Watching for the if there is a error in a create dataverse operation
+ this.store.select(s => s.dataverse.createDataverseError).subscribe((data: any) => {
+ if (data.errors) {
+ this.errorMessage = "ERROR: " + data.errors[0].msg;
+ }
+ })
+
+ // Watching for the if there is a change in the collection
+ this.store.select(s => s.dataverse.dropDataverseSuccess).subscribe((data: any) => {
+ if (data === true) {
+ this.getDataverse();
+ this.errorMessage = "SUCCEED: DROP DATAVERSE " + this.dvName;
+ }
+ })
+
+ // Watching for the if there is a error in a drop dataverse operation
+ this.store.select(s => s.dataverse.dropDataverseError).subscribe((data: any) => {
+ if (data.errors) {
+ this.errorMessage = "ERROR: " + data.errors[0].msg;
+ }
+ })
+ }
+
+ getDataverse() {
+ // Triggers the effect to refresg the dataverse
+ this.store.dispatch(new dataverseActions.SelectDataverses('-'));
+ }
+
+ ngOnInit() {
+ // Assign the datasource for the table
+ this.dataSource = new DataversesDataSource(this.store);
+ }
+
+ ngAfterViewChecked() {}
+
+ ngAfterViewInit() {}
+
+
+ /*
+ * opens the create dataverse dialog
+ */
+ openCreateDataverseDialog(): void {
+ let dialogRef = this.dialog.open(DialogCreateDataverse, {
+ width: '420px',
+ data: { name: this.dataverseName }
+ });
+
+ dialogRef.afterClosed().subscribe(result => {
+ //reference code
+ //this.dvName = result;
+ });
+ }
+
+ /*
+ * opens the drop dataverse dialog
+ */
+ openDropDataverseDialog(): void {
+ let dialogRef = this.dialog.open(DialogDropDataverse, {
+ width: '420px',
+ data: { name: this.dataverseName }
+ });
+
+ dialogRef.afterClosed().subscribe(result => {
+ this.dataverseName = result;
+ });
+ }
+
+ /*
+ * Clean up the error message on the screen
+ */
+ onClick(): void {
+ this.errorMessage = "";
+ }
+
+ selectedRowIndex: number = -1;
+
+ /* Showing all the datatype metadata information */
+ output: any;
+
+ highlight(row){
+ this.output = JSON.stringify(row, null, 2);
+ }
+
+ @ViewChild('querymetadata') inputQuery;
+
+ /* Cleans up error message */
+ cleanUp() {
+ this.errorMessage = "";
+ // Cascading
+ this.inputQuery.cleanUp();
+ }
+}
+
+@Component({
+ selector: 'dataverse-create-dialog',
+ templateUrl: 'dataverses-create-dialog.component.html',
+ styleUrls: ['dataverses-create-dialog.component.scss']
+})
+
+export class DialogCreateDataverse {
+ constructor( private store: Store<any>,
+ public dialogCreateDvRef: MatDialogRef<DialogCreateDataverse>,
+ @Inject(MAT_DIALOG_DATA) public data: any) { }
+
+ onClick(): void {
+ this.store.dispatch(new dataverseActions.CreateDataverse(this.data.dataverseName));
+ this.dialogCreateDvRef.close(this.data.dataverseName);
+ }
+
+ onNoClick(): void {
+ this.dialogCreateDvRef.close();
+ }
+}
+
+@Component({
+ selector: 'dataverse-drop-dialog',
+ templateUrl: 'dataverses-drop-dialog.component.html',
+ styleUrls: ['dataverses-drop-dialog.component.scss']
+})
+
+export class DialogDropDataverse {
+ constructor( private store: Store<any>,
+ public dialogDropDvRef: MatDialogRef<DialogDropDataverse>,
+ @Inject(MAT_DIALOG_DATA) public data: any) { }
+
+ onClick(): void {
+ this.store.dispatch(new dataverseActions.DropDataverse(this.data.dataverseName));
+ this.dialogDropDvRef.close(this.data.dataverseName);
+ }
+
+ onNoClick(): void {
+ this.dialogDropDvRef.close();
+ }
+}
+
+/**
+ * Data source to provide what data should be rendered in the table. Note that the data source
+ * can retrieve its data in any way. In this case, the data source is provided a reference
+ * to a common data base, ExampleDatabase. It is not the data source's responsibility to manage
+ * the underlying data. Instead, it only needs to take the data and send the table exactly what
+ * should be rendered.
+ */
+ export class DataversesDataSource extends DataSource<any> {
+ dataverse$: Observable<any>
+ _filterChange = new BehaviorSubject('');
+ get filter(): string { return this._filterChange.value; }
+ set filter(filter: string) { this._filterChange.next(filter); }
+
+ constructor(private store: Store<any>) {
+ super();
+ this.dataverse$ = this.store.select(s => s.dataverse.dataverses.results);
+ }
+
+ /** Connect function called by the table to retrieve one stream containing the data to render. */
+ connect(): Observable<Dataverse[]> {
+ const displayDataChanges = [
+ this.dataverse$,
+ ];
+
+ return this.dataverse$;
+ }
+
+ disconnect() {}
+ }
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/index-create-dialog.component.html
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/index-create-dialog.component.html b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/index-create-dialog.component.html
new file mode 100755
index 0000000..aca06fd
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/index-create-dialog.component.html
@@ -0,0 +1,14 @@
+<!--/*
+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 -->
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/index-create-dialog.component.scss
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/index-create-dialog.component.scss b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/index-create-dialog.component.scss
new file mode 100755
index 0000000..039dcf1
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/index-create-dialog.component.scss
@@ -0,0 +1,18 @@
+/*
+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.
+*/
+.index-dialog {
+ font-family: "Roboto Mono", monospace;
+ font-size: 0.80rem;
+ font-weight: 500;
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/index-drop-dialog.component.html
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/index-drop-dialog.component.html b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/index-drop-dialog.component.html
new file mode 100755
index 0000000..5e675d8
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/index-drop-dialog.component.html
@@ -0,0 +1,26 @@
+<!--/*
+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="index-dialog">
+ <p mat-dialog-title>DROP INDEX</p>
+ <mat-dialog-content>
+ <p>PLEASE GIVE THE DATAVERSENAME.INDEXNAME OF THE INDEX TO DROP</p>
+ </mat-dialog-content>
+ <mat-form-field>
+ <input matInput tabindex="0" [(ngModel)]="data.indexName">
+ </mat-form-field>
+ <mat-dialog-actions>
+ <button mat-button (click)="onClick()" tabindex="1">DROP</button>
+ <button mat-button (click)="onNoClick()" tabindex="2">CANCEL</button>
+ </mat-dialog-actions>
+</div>
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/index-drop-dialog.component.scss
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/index-drop-dialog.component.scss b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/index-drop-dialog.component.scss
new file mode 100755
index 0000000..039dcf1
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/index-drop-dialog.component.scss
@@ -0,0 +1,18 @@
+/*
+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.
+*/
+.index-dialog {
+ font-family: "Roboto Mono", monospace;
+ font-size: 0.80rem;
+ font-weight: 500;
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/indexes.component.html
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/indexes.component.html b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/indexes.component.html
new file mode 100755
index 0000000..c63b254
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/indexes.component.html
@@ -0,0 +1,94 @@
+<!--/*
+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="container" (click)="onClick()">
+ <div class="master">
+ <mat-card class="indexes-card" *ngIf="loaded$ | async as ld">
+ <mat-toolbar color="primary" class="indexes-selector">
+ <mat-icon class="icon">menu</mat-icon>
+ <span>INDEXES - METADATA</span>
+ <span class="spacer"></span>
+ </mat-toolbar>
+ <mat-card-content class="indexes-content">
+ <mat-table #table [dataSource]="dataSource" class="indexes-table">
+ <!-- Dataverse Name -->
+ <ng-container matColumnDef="DataverseName">
+ <mat-header-cell *matHeaderCellDef class="header-dataversename-cell"> Dataverse Name </mat-header-cell>
+ <mat-cell *matCellDef="let element" class="indexes-dataversename-cell"> {{element.DataverseName}} </mat-cell>
+ </ng-container>
+
+ <!-- Dataset Name -->
+ <ng-container matColumnDef="DatasetName">
+ <mat-header-cell *matHeaderCellDef class="header-datasetname-cell"> Dataset Name </mat-header-cell>
+ <mat-cell *matCellDef="let element" class="indexes-datasetname-cell"> {{element.DatasetName}} </mat-cell>
+ </ng-container>
+
+ <!-- Index Name -->
+ <ng-container matColumnDef="IndexName">
+ <mat-header-cell *matHeaderCellDef class="header-indexname-cell"> Index Name </mat-header-cell>
+ <mat-cell *matCellDef="let element" class="indexes-indexname-cell"> {{element.IndexName}} </mat-cell>
+ </ng-container>
+
+ <!-- Index Structure -->
+ <ng-container matColumnDef="IndexStructure">
+ <mat-header-cell *matHeaderCellDef class="header-indexestructure-cell"> Index Structure </mat-header-cell>
+ <mat-cell *matCellDef="let element" class="indexes-indexstructure-cell"> {{element.IndexStructure}} </mat-cell>
+ </ng-container>
+
+ <!-- IsPrimary -->
+ <ng-container matColumnDef="IsPrimary">
+ <mat-header-cell *matHeaderCellDef class="header-isprimary-cell"> Is Primary </mat-header-cell>
+ <mat-cell *matCellDef="let element" class="indexes-isprimary-cell"> {{element.IsPrimary}} </mat-cell>
+ </ng-container>
+
+ <!-- Timestamp Column -->
+ <ng-container matColumnDef="Timestamp">
+ <mat-header-cell *matHeaderCellDef class="header-timestamp-cell"> Timestamp </mat-header-cell>
+ <mat-cell *matCellDef="let element" class="indexes-timestamp-cell"> {{element.Timestamp}} </mat-cell>
+ </ng-container>
+
+ <!-- Pending Op Column -->
+ <ng-container matColumnDef="PendingOp">
+ <mat-header-cell *matHeaderCellDef class="header-pendingop-cell"> PendingOp </mat-header-cell>
+ <mat-cell *matCellDef="let element" class="indexes-dataverse-cell"> {{element.PendingOp}} </mat-cell>
+ </ng-container>
+
+ <mat-header-row *matHeaderRowDef="['IndexName', 'DatasetName', 'DataverseName', 'IndexStructure', 'IsPrimary', 'Timestamp']"></mat-header-row>
+ <mat-row *matRowDef="let row; columns: ['IndexName', 'DatasetName', 'DataverseName', 'IndexStructure', 'IsPrimary', 'Timestamp'];"
+ [ngClass]="{'highlight': selectedRowIndex == row.id}"
+ (click)="highlight(row)">
+ </mat-row>
+ </mat-table>
+ </mat-card-content>
+ <mat-card-actions class="actions">
+ <button class="refresh-button" mat-button (click)="openDropIndexDialog()">DROP</button>
+ <span class="error-message">{{errorMessage}}</span>
+ <span class="spacer"></span>
+ <button class="refresh-button" mat-button (click)="getIndexes()">REFRESH</button>
+ </mat-card-actions>
+ </mat-card>
+ <awc-query-metadata #querymetadata class="query"></awc-query-metadata>
+ </div>
+ <div class="detail">
+ <mat-card class="indexes-details-card">
+ <mat-toolbar color="primary" class="indexes-selector">
+ <mat-icon class="icon">menu</mat-icon>
+ <span>INDEX - METADATA - DETAILS</span>
+ <span class="spacer"></span>
+ </mat-toolbar>
+ <mat-card-content class="indexes-content output">
+ <span><pre>{{output}}</pre></span>
+ </mat-card-content>
+ </mat-card>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/indexes.component.scss
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/indexes.component.scss b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/indexes.component.scss
new file mode 100755
index 0000000..15b364a
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/indexes.component.scss
@@ -0,0 +1,398 @@
+/*
+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.
+*/
+$indexes-spacing-unit: 8px;
+
+.container {
+ display: flex;
+ flex-flow: row;
+ padding: 0;
+ margin: 0;
+}
+
+.master {
+ width: 60%;
+}
+
+.detail {
+ width: 40%;
+}
+
+.indexes-card {
+ display: flex;
+ flex-flow: column;
+ padding: 0;
+ margin:0 auto;
+ margin-top: ($indexes-spacing-unit * 2);
+ min-height: 450px;
+ max-height: 450px;
+ //min-width: 98%; //(100vw / 2);
+ //max-width: 98%; // (100vw / 2);
+ width: 95%; // 98%;
+ overflow: hidden;
+}
+
+.indexes-details-card {
+ display: flex;
+ flex-flow: column;
+ padding: 0;
+ margin:0 auto;
+ margin: ($indexes-spacing-unit * 2);
+ min-height: 716px;
+ max-height: 716px;
+ //min-width: 95%; //(100vw / 2);
+ //max-width: 95%; // (100vw / 2);
+ overflow: hidden;
+}
+
+.icon {
+ padding: 0 14px 0 0;
+ margin: 0;
+}
+
+.spacer {
+ flex: 1 1 auto;
+}
+
+.indexes-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);
+}
+
+.indexes-content {
+ position:relative;
+ top: 0;
+ left: 0;
+ margin: 0px;
+ padding: 0px;
+ overflow: auto;
+}
+
+.indexes-table {
+ margin: $indexes-spacing-unit !important;
+ height: 330px;
+ overflow: auto;
+}
+
+.spacer {
+ flex: 1 1 auto;
+}
+
+//.indexes-toolbar {
+// display: block;
+// min-height: 56px;
+// height: 56px;
+ //width: 250px;
+// font-size: 12px;
+// white-space: nowrap;
+// overflow: hidden;
+// text-overflow: ellipsis;
+// letter-spacing: 1px;
+// font-weight: 400;
+// background: rgba(0,0,1, .80);
+//}
+
+.example-header {
+ min-height: 64px;
+ display: flex;
+ align-items: center;
+ padding-left: 24px;
+ font-size: 20px;
+}
+
+.mat-table {
+ overflow: auto;
+}
+
+.customWidthClass{
+ flex: 0 0 75px;
+}
+
+.mat-column-DataverseName {
+ text-align: left;
+}
+
+.mat-header-cell.mat-column-DataverseName {
+ text-align: left;
+}
+
+.mat-cell.mat-column-DataverseName {
+ text-align: left;
+}
+
+.header-dataversename-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $indexes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($indexes-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ text-transform: uppercase;
+ flex: 0 0 150px;
+}
+
+.indexes-dataversename-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $indexes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($indexes-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ flex: 0 0 150px;
+}
+
+.header-datasetname-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $indexes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($indexes-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ text-transform: uppercase;
+ flex: 0 0 150px;
+}
+
+.indexes-datasetname-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $indexes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($indexes-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ flex: 0 0 150px;
+}
+
+.header-indexname-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $indexes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($indexes-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ text-transform: uppercase;
+ flex: 0 0 150px;
+}
+
+.indexes-indexname-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $indexes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($indexes-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ flex: 0 0 150px;
+}
+
+.header-indexestructure-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $indexes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($indexes-spacing-unit * 2);
+ text-align: center;
+ color: hsla(0,0%,0%,.87);
+ text-transform: uppercase;
+ flex: 0 0 150px;
+}
+
+.indexes-indexstructure-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $indexes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($indexes-spacing-unit * 2);
+ text-align: center;
+ color: hsla(0,0%,0%,.87);
+ flex: 0 0 150px;
+}
+
+.header-isprimary-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $indexes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($indexes-spacing-unit * 2);
+ text-align: center;
+ color: hsla(0,0%,0%,.87);
+ text-transform: uppercase;
+ flex: 0 0 150px;
+}
+
+.indexes-isprimary-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $indexes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($indexes-spacing-unit * 2);
+ text-align: center;
+ color: hsla(0,0%,0%,.87);
+ flex: 0 0 150px;
+}
+
+.header-timestamp-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $indexes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($indexes-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ text-transform: uppercase;
+ flex: 0 0 150px;
+}
+
+.indexes-timestamp-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $indexes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($indexes-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ flex: 0 0 150px;
+}
+
+.header-groupname-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $indexes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($indexes-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ text-transform: uppercase;
+ flex: 0 0 150px;
+}
+
+.indexes-groupname-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $indexes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($indexes-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ flex: 0 0 150px;
+}
+
+.header-timestamp-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $indexes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($indexes-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ text-transform: uppercase;
+ flex: 0 0 250px;
+}
+
+.indexes-timestamp-cell {
+ border: none;
+ font-size: 12px;
+ letter-spacing: 1px;
+ line-height: $indexes-spacing-unit * 3;
+ font-weight: 400;
+ margin: 0;
+ padding: 0 ($indexes-spacing-unit * 2);
+ text-align: left;
+ color: hsla(0,0%,0%,.87);
+ flex: 0 0 250px;
+}
+
+.example-header {
+ min-height: 56px;
+ max-height: 56px;
+ display: flex;
+ align-items: center;
+ padding: 8px 24px 0;
+ font-size: 20px;
+ justify-content: space-between;
+ border-bottom: 1px solid transparent;
+}
+
+.mat-form-field {
+ font-size: 14px;
+ flex-grow: 1;
+ margin-top: 8px;
+}
+
+.example-no-results {
+ display: flex;
+ justify-content: center;
+ padding: 24px;
+ font-size: 12px;
+ font-style: italic;
+}
+
+.actions {
+ display: flex;
+ border-top: 1px solid rgba(0, 0, 0, 0.1);
+ color: rgba(54, 147, 209, 0.87);
+ padding: $indexes-spacing-unit;
+ margin: 0;
+}
+
+.error-message {
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
+ color: rgba(209, 54, 54, 0.87);
+ padding-top: 10px;
+ padding-left: 20px;
+ text-overflow: ellipsis;
+}
+
+.output {
+ padding-left: ($indexes-spacing-unit * 2);
+}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/indexes.component.ts
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/indexes.component.ts b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/indexes.component.ts
new file mode 100755
index 0000000..2913470
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/indexes-collection/indexes.component.ts
@@ -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.
+*/
+import { Component, Inject, Input } from '@angular/core';
+import { Index } from '../../../shared/models/asterixDB.model'
+import { Store } from '@ngrx/store';
+import { Observable } from 'rxjs/Observable';
+import * as indexActions from '../../../shared/actions/index.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 { State } from '../../../shared/reducers/index.reducer';
+import { MatPaginator } from '@angular/material';
+import { SelectionModel } from '@angular/cdk/collections';
+import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material';
+
+/**
+ * Root component
+ * Defines our application's layout
+ */
+@Component({
+ selector: 'awc-indexes',
+ templateUrl: 'indexes.component.html',
+ styleUrls: ['indexes.component.scss']
+})
+
+export class IndexCollection {
+ displayedColumns = "['dataverseName', 'datasetName', 'indexName', 'indexStructure', 'isPrimary', 'timestamp', 'pendingOp']"
+ /*
+ dataverseName: string;
+ datasetName: string;
+ indexName: string;
+ indexStructure: string;
+ searchKey: string[];
+ isPrimary: boolean;
+ timestamp: string;
+ pendingOp: string;
+ */
+ indexName: string;
+ dataSource: IndexDataSource | null;
+ loaded$: Observable<any>;
+ @Input('message') errorMessage: string = ""
+
+ idxName = "";
+
+ constructor(private store: Store<any>, public dialog: MatDialog) {
+ this.loaded$ = this.store.select('index');
+ // Watching the name of the latest create index
+ this.store.select(s => s.index.createIndexName).subscribe((data: any) => {
+ this.idxName = data;
+ })
+
+ // Watching the name of the latest drop index
+ this.store.select(s => s.index.dropIndexName).subscribe((data: any) => {
+ this.idxName = data;
+ })
+
+ // Watching for the if there is a change in the collection
+ this.store.select(s => s.index.createIndexSuccess).subscribe((data: any) => {
+ if (data === true) {
+ this.getIndexes();
+ this.errorMessage = "SUCCEED: CREATE INDEX " + this.idxName;
+ }
+ })
+
+ // Watching for the if there is a error in a create index operation
+ this.store.select(s => s.index.createIndexError).subscribe((data: any) => {
+ if (data.errors) {
+ this.errorMessage = "ERROR: " + data.errors[0].msg;
+ }
+ })
+
+ // Watching for the success message in a drop index operation
+ this.store.select(s => s.index.dropIndexSuccess).subscribe((data: any) => {
+ if (data === true) {
+ this.getIndexes();
+ this.errorMessage = "SUCCEED: DROP INDEX " + this.idxName;
+ }
+ })
+
+ // Watching for the if there is a error in a drop index operation
+ this.store.select(s => s.index.dropIndexError).subscribe((data: any) => {
+ if (data.errors) {
+ this.errorMessage = "ERROR: " + data.errors[0].msg;
+ }
+ })
+ }
+
+ getIndexes() {
+ // Triggers the effect to refresg the indexes
+ this.store.dispatch(new indexActions.SelectIndexes('-'));
+ }
+
+ ngOnInit() {
+ // Assign the datasource for the table
+ this.dataSource = new IndexDataSource(this.store);
+ }
+
+ /*
+ * opens the create index dialog
+ */
+ openCreateIndexDialog(): void {
+ let dialogRef = this.dialog.open(DialogCreateIndex, {
+ width: '420px',
+ data: { name: this.indexName }
+ });
+
+ dialogRef.afterClosed().subscribe(result => {
+ this.indexName = result;
+ });
+ }
+
+
+ /*
+ * opens the drop index dialog
+ */
+ openDropIndexDialog(): void {
+ let dialogRef = this.dialog.open(DialogDropIndex, {
+ width: '420px',
+ data: { name: this.indexName }
+ });
+
+ dialogRef.afterClosed().subscribe(result => {
+ this.indexName = result;
+ });
+ }
+
+ /*
+ * Clean up the error message on the screen
+ */
+ onClick(): void {
+ this.errorMessage = "";
+ }
+
+ /* Showing all the index metadata information */
+ output: any;
+
+ highlight(row){
+ this.output = JSON.stringify(row, null, 2);
+ }
+
+ @ViewChild('querymetadata') inputQuery;
+
+ /* Cleans up error message */
+ cleanUp() {
+ this.errorMessage = "";
+ // Cascading
+ this.inputQuery.cleanUp();
+ }
+}
+
+@Component({
+ selector: 'index-create-dialog',
+ templateUrl: 'index-create-dialog.component.html',
+ styleUrls: ['index-create-dialog.component.scss']
+})
+
+export class DialogCreateIndex {
+ constructor( private store: Store<any>,
+ public dialogCreateIdxRef: MatDialogRef<DialogCreateIndex>,
+ @Inject(MAT_DIALOG_DATA) public data: any) { }
+
+ onClick(): void {
+ this.store.dispatch(new indexActions.CreateIndex(this.data.indexName));
+ this.dialogCreateIdxRef.close();
+ }
+
+ onNoClick(): void {
+ this.dialogCreateIdxRef.close();
+ }
+}
+
+@Component({
+ selector: 'index-drop-dialog',
+ templateUrl: 'index-drop-dialog.component.html',
+ styleUrls: ['index-drop-dialog.component.scss']
+})
+
+export class DialogDropIndex {
+ constructor( private store: Store<any>,
+ public dialogDropIdxRef: MatDialogRef<DialogDropIndex>,
+ @Inject(MAT_DIALOG_DATA) public data: any) { }
+
+ onClick(): void {
+ console.log(this.data.indexName)
+ this.store.dispatch(new indexActions.DropIndex(this.data.indexName));
+ this.dialogDropIdxRef.close();
+ }
+
+ onNoClick(): void {
+ this.dialogDropIdxRef.close();
+ }
+}
+
+export class IndexDataSource extends DataSource<any> {
+ private indexes$: Observable<any>
+
+ constructor(private store: Store<any>) {
+ super();
+ this.indexes$ = this.store.select(s => s.index.indexes.results);
+ }
+
+ /** Connect function called by the table to retrieve one stream containing the data to render. */
+ connect(): Observable<Index[]> {
+ const displayDataChanges = [
+ this.indexes$,
+ ];
+
+ return this.indexes$;
+ }
+
+ disconnect() {}
+}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/a7e8dbe3/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/input-metadata.component.html
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/input-metadata.component.html b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/input-metadata.component.html
new file mode 100755
index 0000000..939ab06
--- /dev/null
+++ b/asterixdb/asterix-dashboard/src/main/resources/dashboard/src/app/dashboard/metadata/input-metadata.component.html
@@ -0,0 +1,31 @@
+<!--/*
+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.
+*/ -->
+<mat-card class="input-card" (click)="onClick()">
+ <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-metadata class="code" [(ngModel)]="queryMetadataString" [config]="codemirrorMetadataConfig">
+ </codemirror-metadata>
+ </div>
+ </mat-card-content>
+ <mat-card-actions class="actions">
+ <button mat-button class="query-button" (click)="executeQuery()">RUN</button>
+ <span class="error-message">{{errorMessage}}</span>
+ <span class="spacer"></span>
+ </mat-card-actions>
+</mat-card>
\ No newline at end of file