http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/codemirror-metadata.component.ts ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/codemirror-metadata.component.ts b/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/codemirror-metadata.component.ts new file mode 100755 index 0000000..aed6ddf --- /dev/null +++ b/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/codemirror-metadata.component.ts @@ -0,0 +1,244 @@ +/* +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, + ChangeDetectionStrategy + } from '@angular/core'; + import { NG_VALUE_ACCESSOR } from '@angular/forms'; + import * as CodeMirrorMetadata from 'codemirror'; + + /** + * CodeMirror component + * Usage : + * <codemirror [(ngModel)]="data" [config]="{...}"></codemirror> + */ + @Component({ + moduleId: module.id, + selector: 'codemirror-metadata', + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => CodemirrorMetadataComponent), + multi: true + } + ], + styleUrls: ['codemirror-metadata.component.scss'], + template: `<textarea class="textarea-metadata" #hostMetadata></textarea>`,//, + }) + +export class CodemirrorMetadataComponent implements AfterViewInit, OnDestroy { + @Input() config; + @Output() change = new EventEmitter(); + @Output() focus = new EventEmitter(); + @Output() blur = new EventEmitter(); + @Output() instance = null; + @ViewChild('hostMetadata') hostMetadata; + _value = ''; + + /** + * Constructor + */ + constructor(){ + /** + * Custom mode for AsterixDB + */ + CodeMirrorMetadata.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 + */ + codemirrorMetadataConfig = { mode: "asterix", + //lineNumbers: true, + lineWrapping: true, + showCursorWhenSelecting: true, + autofocus: true + }; + + codemirrorInit(config){ + this.instance = CodeMirrorMetadata.fromTextArea(this.hostMetadata.nativeElement, this.codemirrorMetadataConfig); + this.instance.setSize("100%" , "100px"); + 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;} +} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/dataset-create-dialog.component.html ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/dataset-create-dialog.component.html b/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/dataset-create-dialog.component.html new file mode 100755 index 0000000..ef88719 --- /dev/null +++ b/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/dataset-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 --> http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/dataset-create-dialog.component.scss ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/dataset-create-dialog.component.scss b/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/dataset-create-dialog.component.scss new file mode 100755 index 0000000..c969489 --- /dev/null +++ b/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/dataset-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. +*/ +.dataset-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/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/dataset-drop-dialog.component.html ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/dataset-drop-dialog.component.html b/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/dataset-drop-dialog.component.html new file mode 100755 index 0000000..517006c --- /dev/null +++ b/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/dataset-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="dataset-dialog"> + <p mat-dialog-title>DROP DATASET</p> + <mat-dialog-content> + <p>PLEASE GIVE THE NAME OF THE DATASET TO DROP</p> + </mat-dialog-content> + <mat-form-field> + <input matInput tabindex="0" [(ngModel)]="data.datasetName"> + </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/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/dataset-drop-dialog.component.scss ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/dataset-drop-dialog.component.scss b/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/dataset-drop-dialog.component.scss new file mode 100755 index 0000000..c969489 --- /dev/null +++ b/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/dataset-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. +*/ +.dataset-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/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/datasets.component.html ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/datasets.component.html b/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/datasets.component.html new file mode 100755 index 0000000..f556951 --- /dev/null +++ b/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/datasets.component.html @@ -0,0 +1,112 @@ +<!--/* +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="datasets-card" *ngIf="loaded$ | async as ld"> + <mat-toolbar color="primary" class="datasets-selector"> + <mat-icon class="icon">menu</mat-icon> + <span>DATASETS - METADATA</span> + <span class="spacer"></span> + </mat-toolbar> + <mat-card-content class="datasets-content"> + <mat-table #table [dataSource]="dataSource" class="datasets-table"> + <!-- CompactionPolicy Column --> + <ng-container matColumnDef="CompactionPolicy"> + <mat-header-cell *matHeaderCellDef class="header-compactionpolicy-cell">Compaction Policy</mat-header-cell> + <mat-cell *matCellDef="let element" class="dataset-compactionpolicy-cell"> {{element.CompactionPolicy}} </mat-cell> + </ng-container> + + <!-- DatasetId Column --> + <ng-container matColumnDef="DatasetId"> + <mat-header-cell *matHeaderCellDef class="header-datasetid-cell">Dataset Id</mat-header-cell> + <mat-cell *matCellDef="let element" class="dataset-datasetid-cell"> {{element.DatasetId}} </mat-cell> + </ng-container> + + <!-- DatasetName Column --> + <ng-container matColumnDef="DatasetName"> + <mat-header-cell *matHeaderCellDef class="header-datasetname-cell">Dataset Name</mat-header-cell> + <mat-cell *matCellDef="let element" class="dataset-datasetname-cell"> {{element.DatasetName}} </mat-cell> + </ng-container> + + <!-- DatasetType Column --> + <ng-container matColumnDef="DatasetType"> + <mat-header-cell *matHeaderCellDef class="header-datasettype-cell">Dataset Type</mat-header-cell> + <mat-cell *matCellDef="let element" class="dataset-datasettype-cell"> {{element.DatasetType}} </mat-cell> + </ng-container> + + <!-- DatatypeDataverseName Column --> + <ng-container matColumnDef="DatatypeDataverseName"> + <mat-header-cell *matHeaderCellDef class="header-datatypedataversename-cell">Datatype Dataverse Name</mat-header-cell> + <mat-cell *matCellDef="let element" class="dataset-datatypedataversename-cell"> {{element.DatatypeDataverseName}} </mat-cell> + </ng-container> + + <!-- DatatypeName Column --> + <ng-container matColumnDef="DatatypeName"> + <mat-header-cell *matHeaderCellDef class="header-datatypename-cell">Datatype Name</mat-header-cell> + <mat-cell *matCellDef="let element" class="dataset-datatypename-cell"> {{element.DatatypeName}} </mat-cell> + </ng-container> + + <!-- DataverseName Column --> + <ng-container matColumnDef="DataverseName"> + <mat-header-cell *matHeaderCellDef class="header-dataversename-cell">Dataverse Name</mat-header-cell> + <mat-cell *matCellDef="let element" class="dataset-dataversename-cell"> {{element.DataverseName}} </mat-cell> + </ng-container> + + <!-- GroupName Column --> + <ng-container matColumnDef="GroupName"> + <mat-header-cell *matHeaderCellDef class="header-groupname-cell">Group Name</mat-header-cell> + <mat-cell *matCellDef="let element" class="dataset-groupname-cell"> {{element.GroupName}} </mat-cell> + </ng-container> + + <!-- PendingOp Column --> + <ng-container matColumnDef="PendingOp"> + <mat-header-cell *matHeaderCellDef class="header-pendingop-cell">Pending Op</mat-header-cell> + <mat-cell *matCellDef="let element" class="dataset-pendingop-cell"> {{element.PendingOp}} </mat-cell> + </ng-container> + + <!-- DatasetType Column --> + <ng-container matColumnDef="Timestamp"> + <mat-header-cell *matHeaderCellDef class="header-timestamp-cell">Timestamp</mat-header-cell> + <mat-cell *matCellDef="let element" class="dataset-timestamp-cell"> {{element.Timestamp}} </mat-cell> + </ng-container> + + <mat-header-row *matHeaderRowDef="['DatasetName', 'DataverseName', 'DatatypeName', 'Timestamp']"></mat-header-row> + <mat-row *matRowDef="let row; columns: ['DatasetName', 'DataverseName', 'DatatypeName', '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)="openDropDatasetDialog()">DROP</button> + <span class="error-message">{{errorMessage}}</span> + <span class="spacer"></span> + <button class="refresh-button" mat-button (click)="getDatasets()">REFRESH</button> + </mat-card-actions> + </mat-card> + <awc-query-metadata #querymetadata class="query"></awc-query-metadata> + </div> + <div class="detail"> + <mat-card class="datasets-details-card"> + <mat-toolbar color="primary" class="datasets-selector"> + <mat-icon class="icon">menu</mat-icon> + <span>DATASET - METADATA - DETAILS</span> + <span class="spacer"></span> + </mat-toolbar> + <mat-card-content class="datasets-content output"> + <span><pre>{{output}}</pre></span> + </mat-card-content> + </mat-card> + </div> +</div> http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/datasets.component.scss ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/datasets.component.scss b/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/datasets.component.scss new file mode 100755 index 0000000..38a8272 --- /dev/null +++ b/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/datasets.component.scss @@ -0,0 +1,415 @@ +/* +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. +*/ +$datasets-spacing-unit: 8px; + +.container { + display: flex; + flex-flow: row; + padding: 0; + margin: 0; +} + +.master { + width: 60%; + overflow: hidden; +} + +.detail { + width: 40%; + overflow: hidden; +} + +.datasets-card { + display: flex; + flex-flow: column; + padding: 0; + margin:0 auto; + margin-top: ($datasets-spacing-unit * 2); + min-height: 450px; + max-height: 450px; + //min-width: 98%; //(100vw / 2); + //max-width: 98%; // (100vw / 2); + width: 95%; // 98%; + overflow: hidden; +} + +.datasets-details-card { + display: flex; + flex-flow: column; + padding: 0; + margin:0 auto; + margin: ($datasets-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; +} + +.datasets-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); +} + +.datasets-content { + position:relative; + top: 0; + left: 0; + margin: 0px; + padding: 0px; + overflow: auto; +} + +.datasets-table { + margin: $datasets-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 250px; +} + +.mat-column-DataverseName { + text-align: left; +} + +.mat-header-cell.mat-column-DataverseName { + text-align: left; +} + +.mat-cell.mat-column-DataverseName { + text-align: left; +} + +.header-compactionpolicy-cell { + border: none; + font-size: 12px; + letter-spacing: 1px; + line-height: $datasets-spacing-unit * 3; + font-weight: 400; + margin: 0; + padding: 0 ($datasets-spacing-unit * 2); + text-align: left; + color: hsla(0,0%,0%,.87); + text-transform: uppercase; + flex: 0 0 250px; +} + +.dataset-compactionpolicy-cell { + border: none; + font-size: 12px; + letter-spacing: 1px; + line-height: $datasets-spacing-unit * 3; + font-weight: 400; + margin: 0; + padding: 0 ($datasets-spacing-unit * 2); + text-align: left; + color: hsla(0,0%,0%,.87); + flex: 0 0 250px; +} + +.header-datasetid-cell { + border: none; + font-size: 12px; + letter-spacing: 1px; + line-height: $datasets-spacing-unit * 3; + font-weight: 400; + margin: 0; + padding: 0 ($datasets-spacing-unit * 2); + text-align: left; + color: hsla(0,0%,0%,.87); + text-transform: uppercase; + flex: 0 0 250px; +} + +.dataset-datasetid-cell { + border: none; + font-size: 12px; + letter-spacing: 1px; + line-height: $datasets-spacing-unit * 3; + font-weight: 400; + margin: 0; + padding: 0 ($datasets-spacing-unit * 2); + text-align: left; + color: hsla(0,0%,0%,.87); + flex: 0 0 250px; +} + +.header-datasetname-cell { + border: none; + font-size: 12px; + letter-spacing: 1px; + line-height: $datasets-spacing-unit * 3; + font-weight: 400; + margin: 0; + padding: 0 ($datasets-spacing-unit * 2); + text-align: left; + color: hsla(0,0%,0%,.87); + text-transform: uppercase; + flex: 0 0 250px; +} + +.dataset-datasetname-cell { + border: none; + font-size: 12px; + letter-spacing: 1px; + line-height: $datasets-spacing-unit * 3; + font-weight: 400; + margin: 0; + padding: 0 ($datasets-spacing-unit * 2); + text-align: left; + color: hsla(0,0%,0%,.87); + flex: 0 0 250px; +} + +.header-datasettype-cell { + border: none; + font-size: 12px; + //letter-spacing: 1px; + line-height: $datasets-spacing-unit * 3; + font-weight: 400; + margin: 0; + padding: 0 ($datasets-spacing-unit * 2); + text-align: left; + color: hsla(0,0%,0%,.87); + text-transform: uppercase; + flex: 0 0 250px; +} + +.dataset-datasettype-cell { + border: none; + font-size: 12px; + //letter-spacing: 1px; + line-height: $datasets-spacing-unit * 3; + font-weight: 400; + margin: 0; + padding: 0 ($datasets-spacing-unit * 2); + text-align: left; + color: hsla(0,0%,0%,.87); + flex: 0 0 250px; +} + +.header-datatypedataversename-cell { + border: none; + font-size: 12px; + letter-spacing: 1px; + line-height: $datasets-spacing-unit * 3; + font-weight: 400; + margin: 0; + padding: 0 ($datasets-spacing-unit * 2); + text-align: left; + color: hsla(0,0%,0%,.87); + text-transform: uppercase; + flex: 0 0 250px; +} + +.dataset-datatypedataversename-cell { + border: none; + font-size: 12px; + letter-spacing: 1px; + line-height: $datasets-spacing-unit * 3; + font-weight: 400; + margin: 0; + padding: 0 ($datasets-spacing-unit * 2); + text-align: left; + color: hsla(0,0%,0%,.87); + flex: 0 0 250px; +} + +.header-datatypename-cell { + border: none; + font-size: 12px; + letter-spacing: 1px; + line-height: $datasets-spacing-unit * 3; + font-weight: 400; + margin: 0; + padding: 0 ($datasets-spacing-unit * 2); + text-align: left; + color: hsla(0,0%,0%,.87); + text-transform: uppercase; + flex: 0 0 250px; +} + +.dataset-datatypename-cell { + border: none; + font-size: 12px; + letter-spacing: 1px; + line-height: $datasets-spacing-unit * 3; + font-weight: 400; + margin: 0; + padding: 0 ($datasets-spacing-unit * 2); + text-align: left; + color: hsla(0,0%,0%,.87); + flex: 0 0 250px; +} + +.header-dataversename-cell { + border: none; + font-size: 12px; + letter-spacing: 1px; + line-height: $datasets-spacing-unit * 3; + font-weight: 400; + margin: 0; + padding: 0 ($datasets-spacing-unit * 2); + text-align: left; + color: hsla(0,0%,0%,.87); + text-transform: uppercase; + flex: 0 0 250px; +} + +.dataset-dataversename-cell { + border: none; + font-size: 12px; + letter-spacing: 1px; + line-height: $datasets-spacing-unit * 3; + font-weight: 400; + margin: 0; + padding: 0 ($datasets-spacing-unit * 2); + text-align: left; + color: hsla(0,0%,0%,.87); + flex: 0 0 250px; +} + + +.header-groupname-cell { + border: none; + font-size: 12px; + letter-spacing: 1px; + line-height: $datasets-spacing-unit * 3; + font-weight: 400; + margin: 0; + padding: 0 ($datasets-spacing-unit * 2); + text-align: left; + color: hsla(0,0%,0%,.87); + text-transform: uppercase; + flex: 0 0 250px; +} + +.dataset-groupname-cell { + border: none; + font-size: 12px; + letter-spacing: 1px; + line-height: $datasets-spacing-unit * 3; + font-weight: 400; + margin: 0; + padding: 0 ($datasets-spacing-unit * 2); + text-align: left; + color: hsla(0,0%,0%,.87); + flex: 0 0 250px; +} + +.header-timestamp-cell { + border: none; + font-size: 12px; + letter-spacing: 1px; + line-height: $datasets-spacing-unit * 3; + font-weight: 400; + margin: 0; + padding: 0 ($datasets-spacing-unit * 2); + text-align: left; + color: hsla(0,0%,0%,.87); + text-transform: uppercase; + flex: 0 0 250px; +} + +.dataset-timestamp-cell { + border: none; + font-size: 12px; + letter-spacing: 1px; + line-height: $datasets-spacing-unit * 3; + font-weight: 400; + margin: 0; + padding: 0 ($datasets-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: $datasets-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: ($datasets-spacing-unit * 2); +} + + http://git-wip-us.apache.org/repos/asf/asterixdb/blob/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/datasets.component.ts ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datasets-collection/datasets.component.ts b/asterixdb/asterix-app/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-app/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/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-create-dialog.component.html ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-create-dialog.component.html b/asterixdb/asterix-app/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-app/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/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-create-dialog.component.scss ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-create-dialog.component.scss b/asterixdb/asterix-app/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-app/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/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-drop-dialog.component.html ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-drop-dialog.component.html b/asterixdb/asterix-app/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-app/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/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-drop-dialog.component.scss ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatype-drop-dialog.component.scss b/asterixdb/asterix-app/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-app/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/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatypes.component.html ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatypes.component.html b/asterixdb/asterix-app/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-app/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/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatypes.component.scss ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatypes.component.scss b/asterixdb/asterix-app/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-app/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/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatypes.component.ts ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/datatypes-collection/datatypes.component.ts b/asterixdb/asterix-app/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-app/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/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-create-dialog.component.html ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-create-dialog.component.html b/asterixdb/asterix-app/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-app/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/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-create-dialog.component.scss ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-create-dialog.component.scss b/asterixdb/asterix-app/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-app/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/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-drop-dialog.component.html ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-drop-dialog.component.html b/asterixdb/asterix-app/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-app/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/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-drop-dialog.component.scss ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses-drop-dialog.component.scss b/asterixdb/asterix-app/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-app/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/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses.component.html ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses.component.html b/asterixdb/asterix-app/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-app/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/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses.component.scss ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses.component.scss b/asterixdb/asterix-app/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-app/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/1cb814b4/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses.component.ts ---------------------------------------------------------------------- diff --git a/asterixdb/asterix-app/src/main/resources/dashboard/src/app/dashboard/metadata/dataverses-collection/dataverses.component.ts b/asterixdb/asterix-app/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-app/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() {} + }
