You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@griffin.apache.org by gu...@apache.org on 2018/08/03 07:35:50 UTC
[1/2] incubator-griffin git commit:
[GRIFFIN-164][GRIFFIN-186][GRIFFIN-187] Profiling Re-factor + Regex/Empty
String Support
Repository: incubator-griffin
Updated Branches:
refs/heads/master 1c39b8369 -> d58bd194f
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/step1/step1.component.ts
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/step1/step1.component.ts b/ui/angular/src/app/measure/create-measure/pr/step1/step1.component.ts
new file mode 100644
index 0000000..94e1d37
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/step1/step1.component.ts
@@ -0,0 +1,236 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+import { Component, OnInit, Input, Output, EventEmitter } from "@angular/core";
+import { ServiceService } from "../../../../service/service.service";
+import { TREE_ACTIONS, ITreeOptions } from "angular-tree-component";
+import { HttpClient } from "@angular/common/http";
+import { AfterViewChecked, ElementRef } from "@angular/core";
+import { ProfilingStep1 } from "../pr.component";
+
+export class node {
+ name: string;
+ id: number;
+ children: object[];
+ isExpanded: boolean;
+ cols: Col[];
+ parent: string;
+ location: string;
+}
+
+export class Rule {
+ type: string;
+}
+
+export class Col {
+ name: string;
+ type: string;
+ comment: string;
+ selected: boolean;
+ isNum: boolean;
+ isExpanded: boolean;
+ groupby: string;
+ RE: string;
+ rules: any;
+ newRules: Rule[];
+ constructor(name: string, type: string, comment: string, selected: boolean) {
+ this.name = name;
+ this.type = type;
+ this.comment = comment;
+ this.selected = false;
+ this.isExpanded = false;
+ this.groupby = "";
+ this.rules = [];
+ this.RE = "";
+ this.newRules = [];
+
+ var patt = new RegExp("int|double|float/i");
+ if (patt.test(this.type)) {
+ this.isNum = true;
+ }
+ }
+}
+
+@Component({
+ selector: "app-pr-step-1",
+ templateUrl: "./step1.component.html",
+ providers: [ServiceService],
+ styleUrls: ["./step1.component.css"]
+})
+
+export class PrStep1Component implements AfterViewChecked, OnInit {
+ selectedAll = false;
+
+ @Input() step1: ProfilingStep1;
+ @Output() nextStep: EventEmitter<Object> = new EventEmitter<Object>();
+
+ options: ITreeOptions = {
+ displayField: "name",
+ isExpandedField: "expanded",
+ idField: "id",
+ actionMapping: {
+ mouse: {
+ click: (tree, node, $event) => {
+ if (node.hasChildren) {
+ this.step1.currentDB = node.data.name;
+ this.step1.currentDBStr = this.step1.currentDB + ".";
+ this.step1.currentTable = "";
+ this.step1.schemaCollection = [];
+ this.selectedAll = false;
+ TREE_ACTIONS.TOGGLE_EXPANDED(tree, node, $event);
+ } else if (node.data.cols) {
+ this.step1.currentTable = node.data.name;
+ this.step1.currentDB = node.data.parent;
+ this.step1.schemaCollection = node.data.cols;
+ this.step1.srcname = "source" + new Date().getTime();
+ this.step1.srclocation = node.data.location;
+ this.selectedAll = false;
+ this.step1.selection = [];
+ for (let row of this.step1.schemaCollection) {
+ row.selected = false;
+ }
+ }
+ }
+ }
+ },
+ animateExpand: true,
+ animateSpeed: 30,
+ animateAcceleration: 1.2
+ };
+
+ public visible = false;
+ public visibleAnimate = false;
+
+ toggleSelection(row) {
+ row.selected = !row.selected;
+ var idx = this.step1.selection.indexOf(row);
+ // is currently selected
+ if (idx > -1) {
+ this.step1.selection.splice(idx, 1);
+ this.selectedAll = false;
+ for (let key in this.step1.selectedItems) {
+ if (key === row.name) {
+ delete this.step1.selectedItems[key];
+ }
+ }
+ } else {
+ // is newly selected
+ this.step1.selection.push(row);
+ }
+ if (this.step1.selection.length == 3) {
+ this.selectedAll = true;
+ } else {
+ this.selectedAll = false;
+ }
+ this.setDropdownList();
+ }
+
+ setDropdownList() {
+ if (this.step1.selection) {
+ for (let item of this.step1.selection) {
+ if (item.isNum == true) {
+ this.step1.dropdownList[item.name] = [
+ { id: 1, itemName: "Null Count", category: "Simple Statistics" },
+ { id: 2, itemName: "Distinct Count", category: "Simple Statistics" },
+ { id: 3, itemName: "Total Count", category: "Summary Statistics" },
+ { id: 4, itemName: "Maximum", category: "Summary Statistics" },
+ { id: 5, itemName: "Minimum", category: "Summary Statistics" },
+ { id: 6, itemName: "Average", category: "Summary Statistics" },
+ // {"id":7,"itemName":"Median","category": "Summary Statistics"},
+ // {"id":8,"itemName":"Rule Detection Count","category": "Advanced Statistics"},
+ { id: 9, itemName: "Enum Detection Top5 Count", category: "Advanced Statistics" }
+ ];
+ } else {
+ this.step1.dropdownList[item.name] = [
+ { id: 1, itemName: "Null Count", category: "Simple Statistics" },
+ { id: 2, itemName: "Distinct Count", category: "Simple Statistics" },
+ { id: 3, itemName: "Total Count", category: "Summary Statistics" },
+ // {"id":8,"itemName":"Rule Detection Count","category": "Advanced Statistics"},
+ { id: 9, itemName: "Enum Detection Top5 Count", category: "Advanced Statistics" },
+ { id: 10, itemName:"Regular Expression Detection Count", regex: "", category: "Advanced Statistics"},
+ { id: 11, itemName: "Empty Count", category: "Simple Statistics" }
+ ];
+ }
+ }
+ }
+ }
+
+ toggleAll() {
+ this.selectedAll = !this.selectedAll;
+ this.step1.selection = [];
+
+ for (var i = 0; i < this.step1.schemaCollection.length; i++) {
+ this.step1.schemaCollection[i].selected = this.selectedAll;
+ if (this.selectedAll) {
+ this.step1.selection.push(this.step1.schemaCollection[i]);
+ }
+ }
+ this.setDropdownList();
+ }
+
+ constructor(
+ private elementRef: ElementRef,
+ private http: HttpClient,
+ public serviceService: ServiceService
+ ) {}
+
+ ngOnInit() {
+ if (this.step1.nodeList.length !== 0) return;
+
+ let allDataassets = this.serviceService.config.uri.dataassetlist;
+
+ this.http.get(allDataassets).subscribe(data => {
+ this.step1.nodeList = new Array();
+ let i = 1;
+ this.step1.data = data;
+ for (let db in this.step1.data) {
+ let new_node = new node();
+ new_node.name = db;
+ new_node.id = i;
+ new_node.isExpanded = true;
+ i++;
+ new_node.children = new Array();
+ for (let i = 0; i < this.step1.data[db].length; i++) {
+ let new_child = new node();
+ new_child.name = this.step1.data[db][i]["tableName"];
+ new_node.children.push(new_child);
+ new_child.isExpanded = false;
+ new_child.location = this.step1.data[db][i]["sd"]["location"];
+ new_child.parent = db;
+ new_child.cols = Array<Col>();
+ for (let j = 0; j < this.step1.data[db][i]["sd"]["cols"].length; j++) {
+ let new_col = new Col(
+ this.step1.data[db][i]["sd"]["cols"][j].name,
+ this.step1.data[db][i]["sd"]["cols"][j].type,
+ this.step1.data[db][i]["sd"]["cols"][j].comment,
+ false
+ );
+ new_child.cols.push(new_col);
+ }
+ }
+ this.step1.nodeList.push(new_node);
+ }
+ });
+ }
+
+ nextChildStep() {
+ this.nextStep.emit(this.step1);
+ }
+
+ ngAfterViewChecked() {}
+}
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/step2/step2.component.css
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/step2/step2.component.css b/ui/angular/src/app/measure/create-measure/pr/step2/step2.component.css
new file mode 100644
index 0000000..af2cf72
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/step2/step2.component.css
@@ -0,0 +1,55 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+@import url('../../../../../../node_modules/angular2-toaster/toaster.css');
+@import url('../../../measure.component.css');
+
+fieldset {
+ height: 60vh;
+}
+
+label.stepDesc {
+ padding-left: 30px;
+ padding-right: 30px;
+}
+
+div.btn-container {
+ width: 100%;
+ padding-left: 15px;
+ padding-right: 15px;
+ clear: both;
+}
+
+div.btn-container > button.prev-step {
+ float: left;
+}
+
+div.btn-container > button.next-step {
+ float: right;
+}
+
+div.block {
+ margin: 20px 10px;
+ height: 26px;
+}
+
+div.block input {
+ width: 50%;
+ display: inline-block;
+}
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/step2/step2.component.html
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/step2/step2.component.html b/ui/angular/src/app/measure/create-measure/pr/step2/step2.component.html
new file mode 100644
index 0000000..2be8e20
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/step2/step2.component.html
@@ -0,0 +1,80 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<div class="container-fluid">
+ <label class="stepDesc">Please choose one of the profiling models provided below:</label>
+ <div class="container-fluid" id="notshowrule">
+ <div class="col-md-12 col-lg-12 col-sm-12">
+ <fieldset>
+ <div class="y-scrollable">
+ <div style="display:block">
+ <label style="margin-left:15px">View schema:</label> <i style="color:#fff;font-weight: bold;">{{step1.currentDB}}.{{step1.currentTable}}</i>
+ </div>
+ <div class="col-md-12 col-lg-12 col-sm-12" style="z-index:100;margin-top:5px;">
+ <table class="table table-striped" [mfData]="results" #mf="mfDataTable">
+ <thead>
+ <tr style="background-color:#7D95CC">
+ <th>Column Name</th>
+ <th>Data Type</th>
+ <th>Rule <i style="color:#b2c831;" class="fa fa-question-circle fa-lg"></i><i style="font-family: 'Open Sans', sans-serif;">Click <a (click)="showRule()" class="bark-link po">here</a> to view the rule definition</i></th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr *ngFor="let item of step1.selection">
+ <td class="middle">{{item.name}}</td>
+ <td class="middle">{{item.type}}</td>
+ <td class="col-md-5 middle">
+ <angular2-multiselect [data]="step1.dropdownList[item.name]" name="rules-{{item.name}}" [(ngModel)]="step2.selectedItems[item.name]" [settings]="dropdownSettings"></angular2-multiselect>
+ <div *ngIf="containsRegex(step2.selectedItems[item.name])" class="block">
+ <label class="regex-label">
+ Regular Expression:
+ </label>
+ <input type="text" [(ngModel)]="step2.selectedItems[item.name].regex" class="form-control">
+ </div>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </fieldset>
+ </div>
+ <div class="form-group btn-container">
+ <button class="btn btn-primary btn-o back-step btn-wide pull-left" (click)="prevChildStep()">
+ <i class="fa fa-arrow-circle-left"></i> Back
+ </button>
+ <button class="btn btn-primary btn-o next-step btn-wide pull-right" (click)="nextChildStep()">
+ Next <i class="fa fa-arrow-circle-right"></i>
+ </button>
+ </div>
+ </div>
+
+ <div class="container-fluid formStep" id="showrule" style="display:none;">
+ <div class="col-md-12 col-lg-12 col-sm-12">
+ <fieldset>
+ <app-rule></app-rule>
+ </fieldset>
+ </div>
+ <div class="form-group btn-container">
+ <button class="btn btn-primary btn-o back-step btn-wide pull-left" (click)="back()">
+ <i class="fa fa-arrow-circle-left"></i> Back
+ </button>
+ </div>
+ </div>
+
+</div>
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/step2/step2.component.spec.ts
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/step2/step2.component.spec.ts b/ui/angular/src/app/measure/create-measure/pr/step2/step2.component.spec.ts
new file mode 100644
index 0000000..ca2149a
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/step2/step2.component.spec.ts
@@ -0,0 +1,43 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { PrStep2Component } from './step2.component';
+
+describe('PrStep2Component', () => {
+ let component: PrStep2Component;
+ let fixture: ComponentFixture<PrStep2Component>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ PrStep2Component ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PrStep2Component);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should be created', () => {
+ expect(component).toBeTruthy();
+ });
+});
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/step2/step2.component.ts
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/step2/step2.component.ts b/ui/angular/src/app/measure/create-measure/pr/step2/step2.component.ts
new file mode 100644
index 0000000..cd5314a
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/step2/step2.component.ts
@@ -0,0 +1,77 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+import {Component, EventEmitter, Input, OnInit, Output} from "@angular/core";
+import { AfterViewChecked } from "@angular/core";
+import { AngularMultiSelectModule } from "angular2-multiselect-dropdown/angular2-multiselect-dropdown";
+import { ProfilingStep1, ProfilingStep2 } from './../pr.component'
+
+
+@Component({
+ selector: "app-pr-step-2",
+ templateUrl: "./step2.component.html",
+ styleUrls: ["./step2.component.css"]
+})
+export class PrStep2Component implements AfterViewChecked, OnInit {
+ dropdownSettings = {};
+
+ @Input() step1: ProfilingStep1[];
+ @Input() step2: ProfilingStep2[];
+ @Output() prevStep: EventEmitter<Object> = new EventEmitter<Object>();
+ @Output() nextStep: EventEmitter<Object> = new EventEmitter<Object>();
+
+ constructor() {}
+
+ showRule() {
+ document.getElementById("showrule").style.display = "";
+ document.getElementById("notshowrule").style.display = "none";
+ }
+
+ back() {
+ document.getElementById("showrule").style.display = "none";
+ document.getElementById("notshowrule").style.display = "";
+ }
+
+ nextChildStep() {
+ this.nextStep.emit(this.step2);
+ }
+
+ prevChildStep() {
+ this.prevStep.emit(this.step2);
+ }
+
+ containsRegex(obj){
+ if (!obj) return false;
+ return obj.some(rule =>
+ rule.itemName == 'Regular Expression Detection Count'
+ )
+ }
+
+ ngOnInit() {
+ this.dropdownSettings = {
+ singleSelection: false,
+ text: "Select Rule",
+ enableCheckAll: false,
+ enableSearchFilter: true,
+ classes: "myclass",
+ groupBy: "category"
+ };
+ }
+
+ ngAfterViewChecked() {}
+}
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/step3/step3.component.css
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/step3/step3.component.css b/ui/angular/src/app/measure/create-measure/pr/step3/step3.component.css
new file mode 100644
index 0000000..be33bcc
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/step3/step3.component.css
@@ -0,0 +1,37 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+@import url('../../../../../../node_modules/angular2-toaster/toaster.css');
+@import url('../../../measure.component.css');
+
+fieldset {
+ height: 60vh;
+}
+
+label.stepDesc {
+ padding-left: 30px;
+ padding-right: 30px;
+}
+
+div.btn-container {
+ width: 100%;
+ padding-left: 15px;
+ padding-right: 15px;
+ clear: both;
+}
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/step3/step3.component.html
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/step3/step3.component.html b/ui/angular/src/app/measure/create-measure/pr/step3/step3.component.html
new file mode 100644
index 0000000..b2ed563
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/step3/step3.component.html
@@ -0,0 +1,48 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<div class="container-fluid">
+ <label class="stepDesc">Please complete the partition configuration for {{step1.currentTable}}</label>
+ <div class="container-fluid">
+ <div class="col-md-12 col-lg-12 col-sm-12">
+ <fieldset>
+ <legend>
+ Required Information
+ </legend>
+ <div class="y-scrollable">
+ <div class="form-group" style="text-align:center">
+ Data Source:{{step1.currentDB}}.{{step1.currentTable}}
+ </div>
+ <app-configuration [data]="step3.config" [location]="srclocation" (event)="getData($event)"></app-configuration>
+ </div>
+ </fieldset>
+ </div>
+ <div class="form-group btn-container">
+ <button class="btn btn-primary btn-o back-step btn-wide pull-left" (click)="prevChildStep()">
+ <i class="fa fa-arrow-circle-left"></i> Back
+ </button>
+ <toaster-container></toaster-container>
+ <button class="btn btn-primary btn-o next-step btn-wide pull-right" (click)="nextChildStep()">
+ Next <i class="fa fa-arrow-circle-right"></i>
+ </button>
+ </div>
+ </div>
+</div>
+
+
+
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/step3/step3.component.spec.ts
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/step3/step3.component.spec.ts b/ui/angular/src/app/measure/create-measure/pr/step3/step3.component.spec.ts
new file mode 100644
index 0000000..da5ab2e
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/step3/step3.component.spec.ts
@@ -0,0 +1,43 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { PrStep3Component } from './step3.component';
+
+describe('PrStep3Component', () => {
+ let component: PrStep3Component;
+ let fixture: ComponentFixture<PrStep3Component>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ PrStep3Component ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PrStep3Component);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should be created', () => {
+ expect(component).toBeTruthy();
+ });
+});
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/step3/step3.component.ts
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/step3/step3.component.ts b/ui/angular/src/app/measure/create-measure/pr/step3/step3.component.ts
new file mode 100644
index 0000000..79bf2d9
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/step3/step3.component.ts
@@ -0,0 +1,57 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+import { Component, EventEmitter, Input, OnInit, Output } from "@angular/core";
+import { AfterViewChecked } from "@angular/core";
+import { ProfilingStep1, ProfilingStep2, ProfilingStep3 } from './../pr.component'
+
+@Component({
+ selector: "app-pr-step-3",
+ templateUrl: "./step3.component.html",
+ styleUrls: ["./step3.component.css"]
+})
+export class PrStep3Component implements AfterViewChecked, OnInit {
+ @Input() step1: ProfilingStep1;
+ @Input() step2: ProfilingStep2;
+ @Input() step3: ProfilingStep3;
+
+ @Output() prevStep: EventEmitter<Object> = new EventEmitter<Object>();
+ @Output() nextStep: EventEmitter<Object> = new EventEmitter<Object>();
+
+ constructor() {}
+
+ getData(evt) {
+ this.step3.config = evt;
+ this.step3.timezone = evt.timezone;
+ this.step3.where = evt.where;
+ this.step3.size = evt.num + evt.timetype;
+ this.step3.needpath = evt.needpath;
+ this.step3.path = evt.path;
+ }
+
+ nextChildStep() {
+ this.nextStep.emit(this.step3);
+ }
+
+ prevChildStep() {
+ this.prevStep.emit(this.step3);
+ }
+
+ ngOnInit() {}
+ ngAfterViewChecked() {}
+}
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/step4/step4.component.css
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/step4/step4.component.css b/ui/angular/src/app/measure/create-measure/pr/step4/step4.component.css
new file mode 100644
index 0000000..60d6e32
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/step4/step4.component.css
@@ -0,0 +1,42 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+@import url('../../../../../../node_modules/angular2-toaster/toaster.css');
+@import url('../../../measure.component.css');
+
+label.control-label {
+ margin-top: 7px;
+}
+
+fieldset {
+ height: 60vh;
+}
+
+label.stepDesc {
+ padding-left: 30px;
+ padding-right: 30px;
+}
+
+div.btn-container {
+ width: 100%;
+ padding-left: 15px;
+ padding-right: 15px;
+ clear: both;
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/step4/step4.component.html
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/step4/step4.component.html b/ui/angular/src/app/measure/create-measure/pr/step4/step4.component.html
new file mode 100644
index 0000000..0efec50
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/step4/step4.component.html
@@ -0,0 +1,103 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<div class="container-fluid">
+ <label class="stepDesc">Please enter the required information for the measure!</label>
+ <div class="container-fluid">
+ <div class="col-md-12 col-lg-12 col-sm-12">
+ <fieldset>
+ <legend>
+ Required Information
+ </legend>
+ <div class="y-scrollable">
+ <div class="col-md-12 col-lg-12 col-sm-12" style="margin-top:55px;">
+ <div class="form-group" [ngClass]="{'has-error':prName.dirty&&prName.invalid, 'has-success':prName.valid}">
+ <label class="col-md-2 col-lg-2 col-sm-2 control-label">
+ Measure Name<span class="symbol required"></span>:
+ </label>
+ <div class="col-md-10 col-lg-10 col-sm-10 ">
+ <input type="text" class="form-control" [(ngModel)]="step4.prName" #prName="ngModel" placeholder="Please input the measure name" required pattern="^[a-zA-Z0-9_-]*$">
+ <span class="error text-small block " *ngIf="prName.dirty && (prName.errors?.required)">Measure Name is required</span>
+ <span class="error text-small block " *ngIf="prName.dirty && (prName.errors?.pattern)">Only letter, number, "-" and "_" are allowed</span>
+ </div>
+ </div>
+ </div>
+ <div class="col-md-12 col-lg-12 col-sm-12" style="margin-top:10px;">
+ <div class="form-group">
+ <label class="col-md-2 col-lg-2 col-sm-2 control-label">
+ Measure Description:
+ </label>
+ <div class="col-md-10 col-lg-10 col-sm-10">
+ <input type="text" class="form-control" [(ngModel)]="step4.desc" placeholder="Please input detailed description of your measure" name="desc">
+ </div>
+ </div>
+ </div>
+ <div class="col-md-12 col-lg-12 col-sm-12" style="margin-top:10px;">
+ <div class="form-group">
+ <label for="typeSelector" class="col-md-2 col-lg-2 col-sm-2 control-label">
+ Measure Type:
+ </label>
+ <div class="col-md-10 col-lg-10 col-sm-10">
+ <select id="typeSelector" class="form-control" [(ngModel)]="step4.type" disabled required name="type">
+ <option>{{step4.type}}</option>
+ </select>
+ </div>
+ </div>
+ </div>
+ <div class="col-md-12 col-lg-12 col-sm-12" style="margin-top:10px;">
+ <div class="form-group">
+ <label class="col-md-2 col-lg-2 col-sm-2 control-label">
+ DataSource:
+ </label>
+ <div class="col-md-10 col-lg-10 col-sm-10">
+ <input type="text" class="form-control" name="DataAsset" value="{{step1.currentTable}}" disabled>
+ </div>
+ </div>
+ </div>
+ <div class="col-md-12 col-lg-12 col-sm-12" style="margin-top:10px;">
+ <div class="form-group">
+ <label class="col-md-2 col-lg-2 col-sm-2 control-label">
+ Owner:
+ </label>
+ <div class="col-md-10 col-lg-10 col-sm-10">
+ <input type="text" class="form-control" name="owner" disabled [(ngModel)]="step4.owner">
+ </div>
+ </div>
+ </div>
+ </div>
+ <div style="color:#b2c831">
+ <p>
+ <i class="fa fa-info-circle"></i> After submitted, please go to "<a class="bark-link" routerLink="/measures">Measures</a>" to check the measure status
+ </p>
+ </div>
+ </fieldset>
+ </div>
+ <div class="form-group btn-container">
+ <button class="btn btn-primary btn-o back-step btn-wide pull-left" (click)="prevChildStep()">
+ <i class="fa fa-arrow-circle-left"></i> Back
+ </button>
+ <toaster-container></toaster-container>
+ <button type="submit" (click)="submit()" class="btn btn-primary btn-o next-step btn-wide pull-right">
+ Submit
+ </button>
+ </div>
+ </div>
+</div>
+
+
+
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/step4/step4.component.spec.ts
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/step4/step4.component.spec.ts b/ui/angular/src/app/measure/create-measure/pr/step4/step4.component.spec.ts
new file mode 100644
index 0000000..c0ba718
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/step4/step4.component.spec.ts
@@ -0,0 +1,43 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { PrStep4Component } from './step4.component';
+
+describe('PrStep4Component', () => {
+ let component: PrStep4Component;
+ let fixture: ComponentFixture<PrStep4Component>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ PrStep4Component ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PrStep4Component);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should be created', () => {
+ expect(component).toBeTruthy();
+ });
+});
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/step4/step4.component.ts
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/step4/step4.component.ts b/ui/angular/src/app/measure/create-measure/pr/step4/step4.component.ts
new file mode 100644
index 0000000..f3178af
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/step4/step4.component.ts
@@ -0,0 +1,59 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+import {Component, EventEmitter, Input, OnInit, Output, ChangeDetectorRef, AfterViewInit} from "@angular/core";
+import { FormControl } from "@angular/forms";
+import { FormsModule } from "@angular/forms";
+import { AfterViewChecked, ElementRef } from "@angular/core";
+import {ProfilingStep1, ProfilingStep2, ProfilingStep3, ProfilingStep4} from "../pr.component";
+
+@Component({
+ selector: "app-pr-step-4",
+ templateUrl: "./step4.component.html",
+ providers: [],
+ styleUrls: ["./step4.component.css"]
+})
+export class PrStep4Component implements AfterViewChecked, OnInit, AfterViewInit {
+
+ @Input() step1: ProfilingStep1;
+ @Input() step2: ProfilingStep2;
+ @Input() step3: ProfilingStep3;
+ @Input() step4: ProfilingStep4;
+
+ @Output() prevStep: EventEmitter<Object> = new EventEmitter<Object>();
+ @Output() submitMeasure: EventEmitter<Object> = new EventEmitter<Object>();
+
+ constructor(private cdr: ChangeDetectorRef) {}
+
+ prevChildStep() {
+ this.prevStep.emit(this.step4);
+ console.log(this.step4);
+ }
+
+ submit() {
+ this.submitMeasure.emit(this.step4);
+ }
+
+ ngOnInit() {}
+
+ ngAfterViewInit() {
+ this.cdr.detectChanges();
+ }
+
+ ngAfterViewChecked() {}
+}
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pub/pub.component.css
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pub/pub.component.css b/ui/angular/src/app/measure/create-measure/pub/pub.component.css
index 5af6bbe..194a251 100644
--- a/ui/angular/src/app/measure/create-measure/pub/pub.component.css
+++ b/ui/angular/src/app/measure/create-measure/pub/pub.component.css
@@ -201,7 +201,6 @@ under the License.
background-color: #000000;
border-radius: 5px;
padding: 10px;
- max-height: 600px;
/*height:800px;*/
}
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/measure.component.css
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/measure.component.css b/ui/angular/src/app/measure/measure.component.css
index ba60eab..0483912 100644
--- a/ui/angular/src/app/measure/measure.component.css
+++ b/ui/angular/src/app/measure/measure.component.css
@@ -55,10 +55,9 @@ under the License.
.swMain>ul {
display: table;
list-style: none;
- margin: 0 0 20px;
+ margin: 0 30px 20px 30px;
padding: 10px 0;
position: relative;
- width: 100%;
background: #f7f7f8;
border-radius: 5px
}
@@ -67,7 +66,6 @@ under the License.
background-color: #000000;
border-radius: 5px;
padding: 10px;
- max-height: 600px;
/*height:800px;*/
}
@@ -192,7 +190,6 @@ under the License.
.swMain .y-scrollable {
overflow-y: auto;
overflow-x: hidden;
- max-height: 600px;
}
fieldset {
@@ -397,4 +394,4 @@ a {
}
.swMain>ul li>div.selected1child .stepNumber {
border-color: #007AFF
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/styles.css
----------------------------------------------------------------------
diff --git a/ui/angular/src/styles.css b/ui/angular/src/styles.css
index 0ce15db..3f9f559 100644
--- a/ui/angular/src/styles.css
+++ b/ui/angular/src/styles.css
@@ -891,7 +891,7 @@ a:hover {
}
}
-@media (max-width: 991px) {
+@media (max-width: 991px) {
#footerwrap {
width: 100%
}
@@ -1074,7 +1074,7 @@ tbody {
.normal{
background-color: #00C853;
- border-radius: 5px;
+ border-radius: 5px;
padding:3px 4px;
display: inline-block;
width: 70px;
@@ -1083,7 +1083,7 @@ tbody {
.unnormal{
background-color: #EF5350;
- border-radius: 5px;
+ border-radius: 5px;
padding:3px 4px;
display: inline-block;
width: 70px;
@@ -1094,7 +1094,7 @@ tbody {
position: absolute;
z-index:1;
height:100px;
- background-color:white;
+ background-color:white;
/*width:80%;*/
text-align: center;
border: 5px solid #c5c5c5;
@@ -1112,7 +1112,7 @@ tbody {
width:20%;
height:100%;
display: inline-block;
-
+
}
@@ -1120,7 +1120,7 @@ tbody {
width:20%;
height:100%;
display: inline-block;
-
+
}
#pmam{
@@ -1155,7 +1155,7 @@ tbody {
}
.myclass * div.selected-list .c-btn , .myclass * ul ,.myclass * div.list-area, .list-filter input{
- background: #dcdad6;
+ background: #dcdad6;
}
.myclass * div.arrow-up{
@@ -1195,4 +1195,5 @@ input{
.y-scrollable {
overflow-y: auto;
overflow-x: hidden;
-}
\ No newline at end of file
+ height: 100%;
+}
[2/2] incubator-griffin git commit:
[GRIFFIN-164][GRIFFIN-186][GRIFFIN-187] Profiling Re-factor + Regex/Empty
String Support
Posted by gu...@apache.org.
[GRIFFIN-164][GRIFFIN-186][GRIFFIN-187] Profiling Re-factor + Regex/Empty String Support
We've been working away on Griffin here at Credit Karma, and we'd love to contribute back!
This PR tackles three separate tasks:
- [GRIFFIN-164](https://issues.apache.org/jira/browse/GRIFFIN-164): Regex Support
- [GRIFFIN-186](https://issues.apache.org/jira/browse/GRIFFIN-186): Create Profiling Measure Re-Factor
- [GRIFFIN-187](https://issues.apache.org/jira/browse/GRIFFIN-187): Empty String Support
The details for each of these tasks can be found in the JIRA tickets linked above!
Author: Spencer Hivert <sp...@creditkarma.com>
Closes #381 from spencer-hivert-ck/shivert/profiling-refactor-and-regex-support.
Project: http://git-wip-us.apache.org/repos/asf/incubator-griffin/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-griffin/commit/d58bd194
Tree: http://git-wip-us.apache.org/repos/asf/incubator-griffin/tree/d58bd194
Diff: http://git-wip-us.apache.org/repos/asf/incubator-griffin/diff/d58bd194
Branch: refs/heads/master
Commit: d58bd194f646e2f0ef3a5c4259b0195a759909f5
Parents: 1c39b83
Author: Spencer Hivert <sp...@creditkarma.com>
Authored: Fri Aug 3 15:35:41 2018 +0800
Committer: William Guo <gu...@apache.org>
Committed: Fri Aug 3 15:35:41 2018 +0800
----------------------------------------------------------------------
.../step/builder/dsl/expr/LogicalExpr.scala | 19 +
.../step/builder/dsl/parser/BasicParser.scala | 8 +-
ui/angular/src/app/app.module.ts | 10 +
.../measure/create-measure/ac/ac.component.css | 12 +-
.../configuration/configuration.component.css | 4 +
.../configuration/configuration.component.html | 6 +-
.../pr/confirmModal/confirmModal.component.css | 24 +
.../pr/confirmModal/confirmModal.component.html | 128 +++
.../confirmModal/confirmModal.component.spec.ts | 43 +
.../pr/confirmModal/confirmModal.component.ts | 46 ++
.../measure/create-measure/pr/pr.component.css | 137 +---
.../measure/create-measure/pr/pr.component.html | 366 +--------
.../measure/create-measure/pr/pr.component.ts | 792 +++++++------------
.../create-measure/pr/step1/step1.component.css | 141 ++++
.../pr/step1/step1.component.html | 78 ++
.../pr/step1/step1.component.spec.ts | 43 +
.../create-measure/pr/step1/step1.component.ts | 236 ++++++
.../create-measure/pr/step2/step2.component.css | 55 ++
.../pr/step2/step2.component.html | 80 ++
.../pr/step2/step2.component.spec.ts | 43 +
.../create-measure/pr/step2/step2.component.ts | 77 ++
.../create-measure/pr/step3/step3.component.css | 37 +
.../pr/step3/step3.component.html | 48 ++
.../pr/step3/step3.component.spec.ts | 43 +
.../create-measure/pr/step3/step3.component.ts | 57 ++
.../create-measure/pr/step4/step4.component.css | 42 +
.../pr/step4/step4.component.html | 103 +++
.../pr/step4/step4.component.spec.ts | 43 +
.../create-measure/pr/step4/step4.component.ts | 59 ++
.../create-measure/pub/pub.component.css | 1 -
.../src/app/measure/measure.component.css | 7 +-
ui/angular/src/styles.css | 17 +-
32 files changed, 1796 insertions(+), 1009 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/measure/src/main/scala/org/apache/griffin/measure/step/builder/dsl/expr/LogicalExpr.scala
----------------------------------------------------------------------
diff --git a/measure/src/main/scala/org/apache/griffin/measure/step/builder/dsl/expr/LogicalExpr.scala b/measure/src/main/scala/org/apache/griffin/measure/step/builder/dsl/expr/LogicalExpr.scala
index af1223f..13317bb 100644
--- a/measure/src/main/scala/org/apache/griffin/measure/step/builder/dsl/expr/LogicalExpr.scala
+++ b/measure/src/main/scala/org/apache/griffin/measure/step/builder/dsl/expr/LogicalExpr.scala
@@ -86,6 +86,25 @@ case class LikeExpr(head: Expr, is: Boolean, value: Expr) extends LogicalExpr {
}
}
+case class RLikeExpr(head: Expr, is: Boolean, value: Expr) extends LogicalExpr {
+
+ addChildren(head :: value :: Nil)
+
+ def desc: String = {
+ val notStr = if (is) "" else " NOT"
+ s"${head.desc}${notStr} RLIKE ${value.desc}"
+ }
+ def coalesceDesc: String = {
+ val notStr = if (is) "" else " NOT"
+ s"${head.coalesceDesc}${notStr} RLIKE ${value.coalesceDesc}"
+ }
+
+ override def map(func: (Expr) => Expr): RLikeExpr = {
+ RLikeExpr(func(head), is, func(value))
+ }
+}
+
+
case class IsNullExpr(head: Expr, is: Boolean) extends LogicalExpr {
addChild(head)
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/measure/src/main/scala/org/apache/griffin/measure/step/builder/dsl/parser/BasicParser.scala
----------------------------------------------------------------------
diff --git a/measure/src/main/scala/org/apache/griffin/measure/step/builder/dsl/parser/BasicParser.scala b/measure/src/main/scala/org/apache/griffin/measure/step/builder/dsl/parser/BasicParser.scala
index ba6ac2c..18f7754 100644
--- a/measure/src/main/scala/org/apache/griffin/measure/step/builder/dsl/parser/BasicParser.scala
+++ b/measure/src/main/scala/org/apache/griffin/measure/step/builder/dsl/parser/BasicParser.scala
@@ -72,6 +72,7 @@ trait BasicParser extends JavaTokenParsers with Serializable {
* <between-expr> ::= <math-expr> [<not>]? <between> (<math-expr> <and> <math-expr> | <range-expr>)
* <range-expr> ::= "(" [<math-expr>]? [, <math-expr>]+ ")"
* <like-expr> ::= <math-expr> [<not>]? <like> <math-expr>
+ * <rlike-expr> ::= <math-expr> [<not>]? <rlike> <math-expr>
* <is-null-expr> ::= <math-expr> <is> [<not>]? <null>
* <is-nan-expr> ::= <math-expr> <is> [<not>]? <nan>
*
@@ -131,6 +132,7 @@ trait BasicParser extends JavaTokenParsers with Serializable {
val AND_ONLY: Parser[String] = """(?i)and\s""".r
val IS: Parser[String] = """(?i)is\s""".r
val LIKE: Parser[String] = """(?i)like\s""".r
+ val RLIKE: Parser[String] = """(?i)rlike\s""".r
val COMPARE: Parser[String] = "=" | "!=" | "<>" | "<=" | ">=" | "<" | ">"
val LOGICAL_UNARY: Parser[String] = NOT
val LOGICAL_BINARIES: Seq[Parser[String]] = Seq((COMPARE), (AND), (OR))
@@ -276,6 +278,7 @@ trait BasicParser extends JavaTokenParsers with Serializable {
* <between-expr> ::= <math-expr> [<not>]? <between> (<math-expr> <and> <math-expr> | <range-expr>)
* <range-expr> ::= "(" [<math-expr>]? [, <math-expr>]+ ")"
* <like-expr> ::= <math-expr> [<not>]? <like> <math-expr>
+ * <rlike-expr> ::= <math-expr> [<not>]? <rlike> <math-expr>
* <is-null-expr> ::= <math-expr> <is> [<not>]? <null>
* <is-nan-expr> ::= <math-expr> <is> [<not>]? <nan>
*
@@ -296,6 +299,9 @@ trait BasicParser extends JavaTokenParsers with Serializable {
def likeExpr: Parser[LogicalExpr] = mathExpression ~ opt(NOT) ~ LIKE ~ mathExpression ^^ {
case head ~ notOpt ~ _ ~ value => LikeExpr(head, notOpt.isEmpty, value)
}
+ def rlikeExpr: Parser[LogicalExpr] = mathExpression ~ opt(NOT) ~ RLIKE ~ mathExpression ^^ {
+ case head ~ notOpt ~ _ ~ value => RLikeExpr(head, notOpt.isEmpty, value)
+ }
def isNullExpr: Parser[LogicalExpr] = mathExpression ~ IS ~ opt(NOT) ~ NULL ^^ {
case head ~ _ ~ notOpt ~ _ => IsNullExpr(head, notOpt.isEmpty)
}
@@ -303,7 +309,7 @@ trait BasicParser extends JavaTokenParsers with Serializable {
case head ~ _ ~ notOpt ~ _ => IsNanExpr(head, notOpt.isEmpty)
}
- def logicalFactor: Parser[LogicalExpr] = (inExpr | betweenExpr | likeExpr | isNullExpr | isNanExpr | mathExpression) ^^ {
+ def logicalFactor: Parser[LogicalExpr] = (inExpr | betweenExpr | likeExpr | rlikeExpr | isNullExpr | isNanExpr | mathExpression) ^^ {
LogicalFactorExpr(_, false, None)
} | LBR ~ logicalExpression ~ RBR ~ opt(asAlias) ^^ {
case _ ~ expr ~ _ ~ aliasOpt => LogicalFactorExpr(expr, true, aliasOpt)
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/app.module.ts
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/app.module.ts b/ui/angular/src/app/app.module.ts
index 8adb212..2c769f3 100644
--- a/ui/angular/src/app/app.module.ts
+++ b/ui/angular/src/app/app.module.ts
@@ -42,6 +42,11 @@ import { DataassetComponent } from './dataasset/dataasset.component';
import { BatchComponent } from './job/create-job/batch/batch.component';
import { AcComponent} from './measure/create-measure/ac/ac.component';
import { PrComponent } from './measure/create-measure/pr/pr.component';
+import { PrStep1Component } from './measure/create-measure/pr/step1/step1.component';
+import { PrStep2Component } from './measure/create-measure/pr/step2/step2.component';
+import { PrStep3Component } from './measure/create-measure/pr/step3/step3.component';
+import { PrStep4Component } from './measure/create-measure/pr/step4/step4.component';
+import { PrConfirmModal } from './measure/create-measure/pr/confirmModal/confirmModal.component';
import { PubComponent } from './measure/create-measure/pub/pub.component';
import { LoginComponent } from './login/login.component';
import { AngularMultiSelectModule } from 'angular2-multiselect-dropdown/angular2-multiselect-dropdown';
@@ -151,6 +156,11 @@ const appRoutes: Routes = [
BatchComponent,
AcComponent,
PrComponent,
+ PrStep1Component,
+ PrStep2Component,
+ PrStep3Component,
+ PrStep4Component,
+ PrConfirmModal,
PubComponent,
LoginComponent,
RuleComponent,
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/ac/ac.component.css
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/ac/ac.component.css b/ui/angular/src/app/measure/create-measure/ac/ac.component.css
index 80b9b91..83562af 100644
--- a/ui/angular/src/app/measure/create-measure/ac/ac.component.css
+++ b/ui/angular/src/app/measure/create-measure/ac/ac.component.css
@@ -20,6 +20,16 @@ under the License.
@import url('../../../../../node_modules/angular2-toaster/toaster.css');
@import url('../../measure.component.css');
+div.formStep {
+ min-height: 65vh;
+ margin-left: 30px;
+ margin-right: 30px;
+}
+
+h5.over-title {
+ margin-left: 30px;
+}
+
div.tree div.tree-children::before,
div.tree::before {
content: "";
@@ -117,4 +127,4 @@ div.tree>treenode>div::before {
div.tree>treenode>div>.node-wrapper>treenodeexpander>.toggle-children-wrapper {
left: 22px
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/configuration/configuration.component.css
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/configuration/configuration.component.css b/ui/angular/src/app/measure/create-measure/configuration/configuration.component.css
index e884cdd..32f3d25 100644
--- a/ui/angular/src/app/measure/create-measure/configuration/configuration.component.css
+++ b/ui/angular/src/app/measure/create-measure/configuration/configuration.component.css
@@ -16,3 +16,7 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
+
+label.control-label {
+ margin-top: 7px;
+}
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/configuration/configuration.component.html
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/configuration/configuration.component.html b/ui/angular/src/app/measure/create-measure/configuration/configuration.component.html
index ae2a1e3..9f4a926 100644
--- a/ui/angular/src/app/measure/create-measure/configuration/configuration.component.html
+++ b/ui/angular/src/app/measure/create-measure/configuration/configuration.component.html
@@ -26,7 +26,7 @@ under the License.
</div>
</div>
</div>
-<div class="col-md-12 col-lg-12 col-sm-12">
+<div class="col-md-12 col-lg-12 col-sm-12" style="margin-top:10px;">
<div class="form-group">
<label class="col-md-2 col-lg-2 col-sm-2 control-label" title="Your minimum partition size">
Partition Size:
@@ -41,7 +41,7 @@ under the License.
</div>
</div>
</div>
-<div class="col-md-12 col-lg-12 col-sm-12">
+<div class="col-md-12 col-lg-12 col-sm-12" style="margin-top:10px;">
<div class="form-group">
<label class="col-md-2 col-lg-2 col-sm-2 control-label">
Time Zone:
@@ -53,7 +53,7 @@ under the License.
</div>
</div>
</div>
-<div class="col-md-12 col-lg-12 col-sm-12" style="height: 30px;">
+<div class="col-md-12 col-lg-12 col-sm-12" style="margin-top: 30px; height: 30px;">
<div class="form-group">
<input style="margin-left:15px" type="checkbox" [checked]="needpath" (change)="needpath=!needpath;upward()">
<label>
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/confirmModal/confirmModal.component.css
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/confirmModal/confirmModal.component.css b/ui/angular/src/app/measure/create-measure/pr/confirmModal/confirmModal.component.css
new file mode 100644
index 0000000..e52c8ac
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/confirmModal/confirmModal.component.css
@@ -0,0 +1,24 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+.viewrule-content {
+ border: 1px solid #fff;
+ border-radius: 4px;
+ padding: 10px;
+}
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/confirmModal/confirmModal.component.html
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/confirmModal/confirmModal.component.html b/ui/angular/src/app/measure/create-measure/pr/confirmModal/confirmModal.component.html
new file mode 100644
index 0000000..92a3afc
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/confirmModal/confirmModal.component.html
@@ -0,0 +1,128 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<div class="modal-dialog modal-xg modal-lg">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" (click)="hideModal()">×</button>
+ <h4 class="modal-title">Create measure with the below information?</h4>
+ </div>
+ <div class="modal-body">
+ <div class="container-fluid" id="viewruleContent" style="overflow:auto;">
+ <div class="row">
+ <h5 class="over-title margin-bottom-15">Basic information</h5>
+ </div>
+ <div class="row">
+ <div class="col-lg-12 col-md-12 col-sm-12">
+ <div id="viewrule-definition" class="viewrule-content">
+ <div class="row">
+ <label class="col-md-4 col-lg-4 col-sm-4">
+ Measure Name:
+ </label>
+ <div class="col-md-8 col-lg-8 col-sm-8 ">
+ {{step4.prName}}
+ </div>
+ </div>
+ <div class="row">
+ <label class="col-md-4 col-lg-4 col-sm-4">
+ Measure Description:
+ </label>
+ <div class="col-md-8 col-lg-8 col-sm-8 ">
+ {{step4.desc}}
+ </div>
+ </div>
+ <div class="row">
+ <label class="col-md-4 col-lg-4 col-sm-4">
+ Measure Type:
+ </label>
+ <div class="col-md-8 col-lg-8 col-sm-8 ">
+ {{step4.type}}
+ </div>
+ </div>
+ <div class="row">
+ <label class="col-md-4 col-lg-4 col-sm-4">
+ DataSource:
+ </label>
+ <div class="col-md-8 col-lg-8 col-sm-8">
+ {{step1.currentDB}}.{{step1.currentTable}}
+ </div>
+ </div>
+ <div class="row" *ngIf="step3.size">
+ <label class="col-md-4 col-lg-4 col-sm-4">
+ Source Partition Size:
+ </label>
+ <div class="col-md-8 col-lg-8 col-sm-8">
+ {{step3.size}}
+ </div>
+ </div>
+ <div class="row">
+ <label class="col-md-4 col-lg-4 col-sm-4">
+ Source Time Zone:
+ </label>
+ <div class="col-md-8 col-lg-8 col-sm-8">
+ {{step3.timezone}}
+ </div>
+ </div>
+ <div class="row" *ngIf="step3.config['where']">
+ <label class="col-md-4 col-lg-4 col-sm-4">
+ Source Where (Parititon):
+ </label>
+ <div class="col-md-8 col-lg-8 col-sm-8">
+ {{step3.config['where']}}
+ </div>
+ </div>
+ <div class="row" *ngIf="step3.config['whereCriteria']">
+ <label class="col-md-4 col-lg-4 col-sm-4">
+ Source Where (Criteria):
+ </label>
+ <div class="col-md-8 col-lg-8 col-sm-8">
+ {{step3.config['whereCriteria']}}
+ </div>
+ </div>
+ <div class="row" *ngIf="step3.needpath && step3.path">
+ <label class="col-md-4 col-lg-4 col-sm-4">
+ Source Path:
+ </label>
+ <div class="col-md-8 col-lg-8 col-sm-8">
+ {{step3.path}}
+ </div>
+ </div>
+ <div class="row">
+ <label class="col-md-4 col-lg-4 col-sm-4">
+ Owner:
+ </label>
+ <div class="col-md-8 col-lg-8 col-sm-8">
+ {{step4.owner}}
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ <h5 class="row">Rules</h5>
+ <div class="row" *ngFor="let index of step4.noderule;">
+ {{index.name}} : {{index.infos}}
+ </div>
+ <br/>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" (click)="hideModal()">Cancel</button>
+ <button type="button" id="save" class="btn btn-primary" (click)="saveModal()">Save</button>
+ </div>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/confirmModal/confirmModal.component.spec.ts
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/confirmModal/confirmModal.component.spec.ts b/ui/angular/src/app/measure/create-measure/pr/confirmModal/confirmModal.component.spec.ts
new file mode 100644
index 0000000..dddc650
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/confirmModal/confirmModal.component.spec.ts
@@ -0,0 +1,43 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { PrConfirmModal } from './confirmModal.component';
+
+describe('PrConfirmModalComponent', () => {
+ let component: PrConfirmModal;
+ let fixture: ComponentFixture<PrConfirmModal>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ PrConfirmModal ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PrConfirmModal);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should be created', () => {
+ expect(component).toBeTruthy();
+ });
+});
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/confirmModal/confirmModal.component.ts
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/confirmModal/confirmModal.component.ts b/ui/angular/src/app/measure/create-measure/pr/confirmModal/confirmModal.component.ts
new file mode 100644
index 0000000..d19022c
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/confirmModal/confirmModal.component.ts
@@ -0,0 +1,46 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+import {Component, EventEmitter, Input, Output} from "@angular/core";
+import {ProfilingStep1, ProfilingStep2, ProfilingStep3, ProfilingStep4} from "../pr.component";
+
+@Component({
+ selector: "app-pr-confirm-modal",
+ templateUrl: "./confirmModal.component.html",
+ styleUrls: ["./confirmModal.component.css"]
+})
+export class PrConfirmModal {
+
+ @Input() step1: ProfilingStep1;
+ @Input() step2: ProfilingStep2;
+ @Input() step3: ProfilingStep3;
+ @Input() step4: ProfilingStep4;
+
+ @Output() hide: EventEmitter<Object> = new EventEmitter<Object>();
+ @Output() saveMeasure: EventEmitter<Object> = new EventEmitter<Object>();
+
+ constructor() {}
+
+ hideModal() {
+ this.hide.emit();
+ }
+
+ saveModal() {
+ this.saveMeasure.emit()
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/pr.component.css
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/pr.component.css b/ui/angular/src/app/measure/create-measure/pr/pr.component.css
index 512868c..8217c9c 100644
--- a/ui/angular/src/app/measure/create-measure/pr/pr.component.css
+++ b/ui/angular/src/app/measure/create-measure/pr/pr.component.css
@@ -20,107 +20,14 @@ under the License.
@import url('../../../../../node_modules/angular2-toaster/toaster.css');
@import url('../../measure.component.css');
-.selected-list .c-list .c-token {
- background: #6faece;
+div.formStep {
+ min-height: 65vh;
+ margin-left: 30px;
+ margin-right: 30px;
}
-div.tree div.tree-children::before,
-div.tree::before {
- content: "";
- position: absolute;
- border-left: 1px dotted #23527c;
- height: 100%;
- top: -14px;
- left: 12px
-}
-
-tree-root {
- color: #999;
-}
-
-div.tree {
- padding-left: 0;
- margin-left: -5px
-}
-
-div.tree div.tree-children {
- position: relative;
- padding-left: 0;
- margin-left: 16px
-}
-
-div.tree div.tree-children::before {
- left: 5px
-}
-
-div.tree treenode>div>.node-wrapper {
- margin-left: 24px
-}
-
-div.tree treenode>div>.node-wrapper>.node-content-wrapper {
- margin-left: 4px
-}
-
-div.tree treenode>div.tree-node-leaf>.node-wrapper {
- margin-left: 0
-}
-
-div.tree treenode>div::before {
- content: "";
- position: absolute;
- border-bottom: 1px dotted #23527c;
- width: 7px;
- margin-top: 12px;
- left: 7px
-}
-
-div.tree treenode>div .toggle-children-wrapper {
- width: 13px;
- height: 13px;
- border: 1px solid #23527c;
- position: absolute;
- left: 15px;
- margin-top: 5px;
- margin-left: 0;
- display: inline-block;
- background-color: #fff;
- z-index: 1
-}
-
-div.tree treenode>div .toggle-children-wrapper::before {
- content: "";
- display: inline-block;
- width: 7px;
- border-top: 1px solid #23527c;
- position: absolute;
- top: 5px;
- left: 2px
-}
-
-div.tree treenode>div .toggle-children-wrapper.toggle-children-wrapper-collapsed::after {
- content: "";
- display: inline-block;
- height: 7px;
- border-left: 1px solid #23527c;
- position: absolute;
- top: 2px;
- left: 5px
-}
-
-div.tree treenode>div .toggle-children-wrapper .toggle-children {
- display: none
-}
-
-div.tree treenode>div .node-content-wrapper {
- margin-left: 4px
-}
-
-div.tree>treenode>div::before {
- left: 14px
-}
-
-div.tree>treenode>div>.node-wrapper>treenodeexpander>.toggle-children-wrapper {
- left: 22px
+h5.over-title {
+ margin-left: 30px;
}
label {
@@ -131,35 +38,3 @@ label {
max-height: 40vh;
overflow-y: scroll;
}
-
-.badgebox {
- opacity: 0;
-}
-
-.badgebox+.badge {
- /* Move the check mark away when unchecked */
- text-indent: -999999px;
- /* Makes the badge's width stay the same checked and unchecked */
- width: 27px;
-}
-
-.badgebox:focus+.badge {
- /* Set something to make the badge looks focused */
- /* This really depends on the application, in my case it was: */
- /* Adding a light border */
- box-shadow: inset 0px 0px 5px;
- /* Taking the difference out of the padding */
-}
-
-.badgebox:checked+.badge {
- /* Move the check mark back when checked */
- text-indent: 0;
-}
-
-.middle {
- vertical-align: middle;
-}
-
-.no-border {
- border: 1px solid transparent !important;
-}
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/pr.component.html
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/pr.component.html b/ui/angular/src/app/measure/create-measure/pr/pr.component.html
index 1767845..22b1f4d 100644
--- a/ui/angular/src/app/measure/create-measure/pr/pr.component.html
+++ b/ui/angular/src/app/measure/create-measure/pr/pr.component.html
@@ -16,378 +16,60 @@ KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
-<div class="container-fluid" (window:resize)="onResize($event)">
+<div class="container-fluid">
<div class="row">
<h5 class="over-title margin-bottom-15">Create Measure</h5>
+ <toaster-container></toaster-container>
</div>
<div class="row">
<form name="Form" id="form" #prForm="ngForm" novalidate>
<div id="wizard" class="swMain">
<ul>
- <li (click)="goTo(1)">
+ <li>
<a [ngClass]="{'selected' : currentStep >= 1, 'done' : currentStep > 1}" class="selected">
- <div class="stepNumber">
- 1
- </div>
- <span class="stepDesc text-small"> Choose Source </span>
+ <div class="stepNumber">1</div>
+ <span class="stepDesc text-small">Choose Source</span>
</a>
</li>
- <li (click)="goTo(2)">
+ <li>
<a [ngClass]="{'selected' : currentStep >= 2, 'done' : currentStep > 2}" class="" style="">
- <div class="stepNumber">
- 2
- </div>
- <span class="stepDesc text-small"> Select Models </span>
+ <div class="stepNumber">2</div>
+ <span class="stepDesc text-small">Select Models</span>
</a>
</li>
- <li (click)="goTo(3)">
+ <li>
<a [ngClass]="{'selected' : currentStep >= 3, 'done' : currentStep > 3}">
- <div class="stepNumber">
- 3
- </div>
- <span class="stepDesc text-small">Partition Configuration </span>
+ <div class="stepNumber">3</div>
+ <span class="stepDesc text-small">Partition Configuration</span>
</a>
</li>
- <li (click)="goTo(4)">
+ <li>
<a [ngClass]="{'selected' : currentStep >= 4, 'done' : currentStep > 4}">
- <div class="stepNumber">
- 4
- </div>
- <span class="stepDesc text-small"> Configuration </span>
+ <div class="stepNumber">4</div>
+ <span class="stepDesc text-small">Configuration</span>
</a>
</li>
</ul>
</div>
+
<div id="step-1" *ngIf="currentStep == 1" class="formStep">
- <label class="stepDesc">This step let you choose the single source of truth for data quality comparision with target. Currently you can only select the attributes from one schema</label>
- <div class="container-fluid">
- <div class="col-md-4 col-lg-4 col-sm-4">
- <fieldset>
- <legend>Please select schema</legend>
- <tree-root [nodes]="nodeList" [options]="options"></tree-root>
- </fieldset>
- </div>
- <div class="col-md-8 col-lg-8 col-sm-8">
- <fieldset>
- <legend>
- Select attributes
- </legend>
- <div class="y-scrollable">
- <div style="margin-top:10px;">
- <label>View schema:</label>
- <i style="color:#fff;font-weight: bold;">{{currentDBstr}}{{currentTable}}
- </i>
- </div>
- <div style="margin-top:5px;">
- <table class="table table-striped no-border">
- <thead>
- <tr style="background-color:#7D95CC">
- <th>
- <input type="checkbox" (click)="toggleAll()" [checked]="selectedAll" />
- </th>
- <th>Column Name</th>
- <th>Type</th>
- <th>Comment</th>
- </tr>
- </thead>
- <tbody>
- <tr *ngIf="!schemaCollection || schemaCollection.length == 0">
- <td colspan="5" style="text-align:center;"><span class="highlight">Please select a schema from the left tree first</span></td>
- </tr>
- <tr *ngFor="let row of schemaCollection">
- <td>
- <input type="checkbox" (click)='toggleSelection(row)' [checked]="row.selected" value={{row.name}} />
- </td>
- <td>{{row.name}}</td>
- <td>{{row.type}}</td>
- <td>{{row.comment}}</td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
- </fieldset>
- </div>
- <div class="form-group btn-container">
- <toaster-container></toaster-container>
- <button class="btn btn-primary btn-o next-step btn-wide pull-right" (click)="next(Form)">
- Next <i class="fa fa-arrow-circle-right"></i>
- </button>
- </div>
- </div>
+ <app-pr-step-1 [step1]='step1' (nextStep)='updateStep1($event)'></app-pr-step-1>
</div>
+
<div id="step-2" *ngIf="currentStep == 2" class="formStep">
- <label class="stepDesc">Please choose one of the profiling models provided below:</label>
- <div class="container-fluid" id="notshowrule">
- <div class="col-md-12 col-lg-12 col-sm-12">
- <!-- <fieldset style="max-height:400px;overflow-y:scroll;"> -->
- <fieldset>
- <div class="y-scrollable">
- <div style="display:block">
- <label style="margin-left:15px">View schema:</label> <i style="color:#fff;font-weight: bold;">{{currentDB}}.{{currentTable}}</i>
- </div>
- <div class="col-md-12 col-lg-12 col-sm-12" style="z-index:100;margin-top:5px;">
- <table class="table table-striped" [mfData]="results" #mf="mfDataTable">
- <thead>
- <tr style="background-color:#7D95CC">
- <th>Column Name</th>
- <th>Data Type</th>
- <th>Rule <i style="color:#b2c831;" class="fa fa-question-circle fa-lg"></i><i style="font-family: 'Open Sans', sans-serif;">Click <a (click)="showRule()" class="bark-link po">here</a> to view the rule definition</i></th>
- </tr>
- </thead>
- <tbody>
- <tr *ngFor="let item of selection">
- <td class="middle">{{item.name}}</td>
- <td class="middle">{{item.type}}</td>
- <td class="col-md-5 middle">
- <angular2-multiselect [data]="dropdownList[item.name]" name="rules-{{item.name}}" [(ngModel)]="selectedItems[item.name]" [settings]="dropdownSettings"></angular2-multiselect>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- <!-- <div *ngFor="let index of transrule"> {{index}}</div> -->
- </div>
- </fieldset>
- </div>
- <div class="form-group btn-container">
- <button class="btn btn-primary btn-o back-step btn-wide pull-left" (click)="prev(Form)">
- <i class="fa fa-arrow-circle-left"></i> Back
- </button>
- <toaster-container></toaster-container>
- <button class="btn btn-primary btn-o next-step btn-wide pull-right" (click)="next(Form)">
- Next <i class="fa fa-arrow-circle-right"></i>
- </button>
- </div>
- </div>
- <div class="container-fluid formStep" id="showrule" style="display:none;">
- <div class="col-md-12 col-lg-12 col-sm-12">
- <fieldset>
- <app-rule></app-rule>
- </fieldset>
- </div>
- <div class="form-group btn-container">
- <button class="btn btn-primary btn-o back-step btn-wide pull-left" (click)="back()">
- <i class="fa fa-arrow-circle-left"></i> Back
- </button>
- </div>
- </div>
+ <app-pr-step-2 [step1]='step1' [step2]='step2' (prevStep)='prev($event)' (nextStep)='updateStep2($event)'></app-pr-step-2>
</div>
+
<div id="step-3" *ngIf="currentStep == 3" class="formStep">
- <label class="stepDesc">Please complete the partition configuration for {{currentTable}}</label>
- <div class="container-fluid">
- <div class="col-md-12 col-lg-12 col-sm-12">
- <fieldset>
- <legend>
- Required Information
- </legend>
- <div class="y-scrollable">
- <div class="col-md-12 col-lg-12 col-sm-12">
- <div class="form-group" style="text-align:center">
- Data Source:{{currentDB}}.{{currentTable}}
- </div>
- <app-configuration [data]="config" [location]="srclocation" (event)="getData($event)"></app-configuration>
- </div>
- </div>
- </fieldset>
- </div>
- <div class="form-group btn-container">
- <button class="btn btn-primary btn-o back-step btn-wide pull-left" (click)="prev(Form)">
- <i class="fa fa-arrow-circle-left"></i> Back
- </button>
- <toaster-container></toaster-container>
- <button class="btn btn-primary btn-o next-step btn-wide pull-right" (click)="next(Form)">
- Next <i class="fa fa-arrow-circle-right"></i>
- </button>
- </div>
- </div>
+ <app-pr-step-3 [step1]='step1' [step2]='step2' [step3]='step3' (prevStep)='prev($event)' (nextStep)='updateStep3($event)'></app-pr-step-3>
</div>
+
<div id="step-4" *ngIf="currentStep == 4" class="formStep">
- <label class="stepDesc">Please setup the measure required information</label>
- <div class="container-fluid">
- <div class="col-md-12 col-lg-12 col-sm-12">
- <fieldset>
- <legend>
- Required Information
- </legend>
- <div class="y-scrollable">
- <div class="col-md-12 col-lg-12 col-sm-12" style="margin-top:30px;">
- <div class="form-group" [ngClass]="{'has-error':prName.dirty&&prName.invalid, 'has-success':prName.valid}">
- <label class="col-md-2 col-lg-2 col-sm-2 control-label">
- Measure Name<span class="symbol required"></span>:
- </label>
- <div class="col-md-10 col-lg-10 col-sm-10 ">
- <input type="text" class="form-control" [(ngModel)]="name" #prName="ngModel" name="prName" placeholder="Please input the measure name" required pattern="^[a-zA-Z0-9_-]*$">
- <span class="error text-small block " *ngIf="prName.dirty && (prName.errors?.required)">Measure Name is required</span>
- <span class="error text-small block " *ngIf="prName.dirty && (prName.errors?.pattern)">Only letter, number, "-" and "_" are allowed</span>
- </div>
- </div>
- </div>
- <div class="col-md-12 col-lg-12 col-sm-12">
- <div class="form-group">
- <label class="col-md-2 col-lg-2 col-sm-2 control-label">
- Measure Description:
- </label>
- <div class="col-md-10 col-lg-10 col-sm-10 ">
- <input type="text" class="form-control" [(ngModel)]="desc" placeholder="Please input detailed description of your measure" name="desc">
- </div>
- </div>
- </div>
- <div class="col-md-12 col-lg-12 col-sm-12">
- <div class="form-group">
- <label for="typeSelector" class="col-md-2 col-lg-2 col-sm-2 control-label">
- Measure Type:<span class="symbol required"></span>:
- </label>
- <div class="col-md-10 col-lg-10 col-sm-10 ">
- <select id="typeSelector" class="form-control" [(ngModel)]="type" disabled required name="type">
- <option>{{type}}</option>
- </select>
- </div>
- </div>
- </div>
- <div class="col-md-12 col-lg-12 col-sm-12">
- <div class="form-group">
- <label class="col-md-2 col-lg-2 col-sm-2 control-label">
- DataSource:<span class="symbol required"></span>:
- </label>
- <div class="col-md-10 col-lg-10 col-sm-10">
- <input type="text" class="form-control" [(ngModel)]="currentTable" #prDataSource="ngModel" name="prDataSource" [readonly]="true" required >
- <span class="error text-small block " *ngIf="prDataSource.dirty && (prDataSource.errors?.required)">Data source is required</span>
- </div>
- </div>
- </div>
- <div class="col-md-12 col-lg-12 col-sm-12">
- <div class="form-group">
- <label class="col-md-2 col-lg-2 col-sm-2 control-label">
- Owner:
- </label>
- <div class="col-md-10 col-lg-10 col-sm-10">
- <input type="text" class="form-control" name="owner" disabled [(ngModel)]="owner">
- </div>
- </div>
- </div>
- </div>
- <div style="color:#b2c831">
- <p>
- <i class="fa fa-info-circle"></i> After submitted, please go to "<a class="bark-link" routerLink="/measures">Measures</a>" to check the measure status
- </p>
- </div>
- </fieldset>
- </div>
- <div class="form-group btn-container">
- <button class="btn btn-primary btn-o back-step btn-wide pull-left" (click)="prev(Form)">
- <i class="fa fa-arrow-circle-left"></i> Back
- </button>
- <toaster-container></toaster-container>
- <button type="submit" (click)="submit(prForm)" class="btn btn-primary btn-o next-step btn-wide pull-right">
- Submit
- </button>
- </div>
- </div>
+ <app-pr-step-4 [step1]='step1' [step2]='step2' [step3]='step3' [step4]='step4' (prevStep)='prev($event)' (submitMeasure)='submit($event)'></app-pr-step-4>
</div>
+
<div class="modal fade" id="confirm" role="dialog" #modal tabindex="-1" [ngClass]="{'in': visibleAnimate}" [ngStyle]="{'display': visible ? 'block' : 'none', 'opacity': visibleAnimate ? 1 : 0}" (click)="onContainerClicked($event)">
- <div class="modal-dialog modal-xg modal-lg">
- <div class="modal-content">
- <div class="modal-header">
- <button type="button" class="close" (click)="hide()">×</button>
- <h4 class="modal-title">Save the measure with the below information?</h4>
- </div>
- <div class="modal-body">
- <div class="container-fluid" id="viewruleContent" style="overflow:auto;">
- <div class="row">
- <h5 class="over-title margin-bottom-15">Basic information</h5>
- </div>
- <div class="row">
- <div class="col-lg-12 col-md-12 col-sm-12">
- <div id="viewrule-definition" class="viewrule-content">
- <div class="row">
- <label class="col-md-4 col-lg-4 col-sm-4">
- Measure Name:
- </label>
- <div class="col-md-8 col-lg-8 col-sm-8 ">
- {{name}}
- </div>
- </div>
- <div class="row">
- <label class="col-md-4 col-lg-4 col-sm-4">
- Measure Description:
- </label>
- <div class="col-md-8 col-lg-8 col-sm-8 ">
- {{desc}}
- </div>
- </div>
- <div class="row">
- <label class="col-md-4 col-lg-4 col-sm-4">
- Measure Type:
- </label>
- <div class="col-md-8 col-lg-8 col-sm-8 ">
- {{type}}
- </div>
- </div>
- <div class="row">
- <label class="col-md-4 col-lg-4 col-sm-4">
- DataSource:
- </label>
- <div class="col-md-8 col-lg-8 col-sm-8" *ngIf="this.currentTable">
- {{currentDB}}.{{currentTable}}
- </div>
- </div>
- <div class="row" *ngIf="this.size">
- <label class="col-md-4 col-lg-4 col-sm-4">
- Source Partition Size:
- </label>
- <div class="col-md-8 col-lg-8 col-sm-8">
- {{this.size}}
- </div>
- </div>
- <div class="row" *ngIf="this.size">
- <label class="col-md-4 col-lg-4 col-sm-4">
- Source Time Zone:
- </label>
- <div class="col-md-8 col-lg-8 col-sm-8">
- {{this.timezone}}
- </div>
- </div>
- <div class="row" *ngIf="this.where">
- <label class="col-md-4 col-lg-4 col-sm-4">
- Source Where:
- </label>
- <div class="col-md-8 col-lg-8 col-sm-8">
- {{this.where}}
- </div>
- </div>
- <div class="row" *ngIf="this.needpath && this.path">
- <label class="col-md-4 col-lg-4 col-sm-4">
- Source Path:
- </label>
- <div class="col-md-8 col-lg-8 col-sm-8">
- {{this.path}}
- </div>
- </div>
- <div class="row">
- <label class="col-md-4 col-lg-4 col-sm-4">
- Owner:
- </label>
- <div class="col-md-8 col-lg-8 col-sm-8">
- {{owner}}
- </div>
- </div>
- </div>
- </div>
- </div>
- <h5 class="row">Rules</h5>
- <div class="row" *ngFor="let index of noderule;">
- {{index.name}} : {{index.infos}}
- </div>
- <br/>
- </div>
- </div>
- <div class="modal-footer">
- <button type="button" class="btn btn-default" (click)="hide()">Cancel</button>
- <button type="button" id="save" class="btn btn-primary" (click)="save()">Save</button>
- </div>
- </div>
- </div>
+ <app-pr-confirm-modal [step1]='step1' [step2]='step2' [step3]='step3' [step4]='step4' (hide)='hide($event)' (saveMeasure)='save($event)'></app-pr-confirm-modal>
</div>
</form>
</div>
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/pr.component.ts
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/pr.component.ts b/ui/angular/src/app/measure/create-measure/pr/pr.component.ts
index b36af39..4b4b747 100644
--- a/ui/angular/src/app/measure/create-measure/pr/pr.component.ts
+++ b/ui/angular/src/app/measure/create-measure/pr/pr.component.ts
@@ -17,64 +17,54 @@ specific language governing permissions and limitations
under the License.
*/
import { Component, OnInit } from "@angular/core";
-import { FormControl } from "@angular/forms";
-import { FormsModule } from "@angular/forms";
import { ServiceService } from "../../../service/service.service";
-import { TREE_ACTIONS, KEYS, IActionMapping, ITreeOptions } from "angular-tree-component";
-import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { ToasterModule, ToasterService, ToasterContainerComponent } from "angular2-toaster";
-import * as $ from "jquery";
import { HttpClient } from "@angular/common/http";
import { Router } from "@angular/router";
-import { DataTableModule } from "angular2-datatable";
import { AfterViewChecked, ElementRef } from "@angular/core";
-import { AngularMultiSelectModule } from "angular2-multiselect-dropdown/angular2-multiselect-dropdown";
-import { ConfigurationComponent } from "../configuration/configuration.component";
-
-class node {
- name: string;
- id: number;
- children: object[];
- isExpanded: boolean;
- cols: Col[];
- parent: string;
- location: string;
+import { Col } from './step1/step1.component'
+import * as $ from "jquery";
+
+export class ProfilingStep1 {
+ data: any;
+ schemaCollection: Col[] = [];
+ nodeList: object[] = [];
+ selection: Col[];
+ dropdownList: object = {};
+ currentDB: string;
+ currentDBStr: string;
+ currentTable: string;
+ srcname: string;
+ srclocation: string;
+ selectedItems: object = {};
}
-class Rule {
- type: string;
+export class ProfilingStep2 {
+ selectedItems: object = {};
}
-class Col {
- name: string;
- type: string;
- comment: string;
- selected: boolean;
- isNum: boolean;
- isExpanded: boolean;
- // rules:string[];
- groupby: string;
- RE: string;
- rules: any;
- newRules: Rule[];
- ruleLength = 0;
- constructor(name: string, type: string, comment: string, selected: boolean) {
- this.name = name;
- this.type = type;
- this.comment = comment;
- this.selected = false;
- this.isExpanded = false;
- this.groupby = "";
- this.rules = [];
- this.RE = "";
- this.newRules = [];
-
- var patt = new RegExp("int|double|float/i");
- if (patt.test(this.type)) {
- this.isNum = true;
- }
- // this.rules = [];
- }
+export class ProfilingStep3 {
+ config: object = {
+ where: "",
+ timezone: "UTC(WET,GMT)",
+ num: 1,
+ timetype: "day",
+ needpath: false,
+ path: ""
+ };
+ timezone: string = "UTC(WET,GMT)";
+ where: string = "";
+ size: string = "1day";
+ needpath: boolean = false;
+ path: string;
+}
+
+export class ProfilingStep4 {
+ prName: string = "";
+ desc: string;
+ type: string = "profiling";
+ owner: string = "test";
+ noderule: object[] = [];
}
@Component({
@@ -84,338 +74,306 @@ class Col {
styleUrls: ["./pr.component.css"]
})
export class PrComponent implements AfterViewChecked, OnInit {
- noderule = [];
+ currentStep = 1;
+
+ step1: ProfilingStep1;
+ step2: ProfilingStep2;
+ step3: ProfilingStep3;
+ step4: ProfilingStep4;
+
transrule = [];
transenumrule = [];
transnullrule = [];
- showrule = false;
- dropdownList = {};
- selectedItems = {};
- allRules = {};
- dropdownSettings = {};
- currentStep = 1;
- firstCond = false;
- mouseover = false;
- selection: Col[];
- selectedAll = false;
- currentDB = "";
- currentTable = "";
- schemaCollection: Col[];
- totallen = 0;
- type = "profiling";
- data: any;
- desc: string;
- owner = "test";
- currentDBstr: string;
- timezone = "";
- ruledesc = "";
- newMeasure = {
- name: "",
- "measure.type": "griffin",
- "dq.type": "PROFILING",
- "process.type": "BATCH",
- owner: "",
- description: "",
- "rule.description": {
- details:[]
- },
- // "group":[],
- "data.sources": [
- {
- name: "source",
- connectors: [
- {
- name: "",
- type: "HIVE",
- version: "1.2",
- "data.unit": "",
- "data.time.zone": "",
- config: {
- database: "",
- "table.name": "",
- where: ""
- },
- predicates: [
- {
- type: "file.exist",
- config: {
- "root.path": '',
- path: ""
- }
- }
- ]
- }
- ]
- }
- ],
- "evaluate.rule": {
- rules: [
- // {
- // "dsl.type": "griffin-dsl",
- // "dq.type": "profiling",
- // rule: "",
- // name: "",
- // }
- ]
- }
- };
- name: "";
+ transregexrule = [];
+ newMeasure = {};
createResult: any;
- newCond: any;
- srclocation: string;
- srcname: string;
- config = {
- where: "",
- timezone: "",
- num: 1,
- timetype: "day",
- needpath: false,
- path: ""
- };
- where: string;
- size: string;
- path: string;
- location: string;
- needpath: boolean;
- private toasterService: ToasterService;
public visible = false;
public visibleAnimate = false;
+ private toasterService: ToasterService;
- public hide(): void {
- this.visibleAnimate = false;
- setTimeout(() => (this.visible = false), 300);
- this.transrule = [];
- this.transenumrule = [];
- this.transnullrule = [];
- this.noderule = [];
- $("#save").removeAttr("disabled");
+ next() {
+ if (this.formValidation(this.currentStep)) {
+ this.currentStep++;
+ } else {
+ this.toasterService.pop(
+ "error",
+ "Error!",
+ "Please select at least one attribute!"
+ );
+ return false;
+ }
}
- public onContainerClicked(event: MouseEvent): void {
- if ((<HTMLElement>event.target).classList.contains("modal")) {
- this.hide();
- }
+ prev() {
+ this.currentStep--;
}
- onResize(event) {
- this.resizeWindow();
+ updateStep1(body:ProfilingStep1) {
+ this.step1 = body;
+ this.next();
}
- resizeWindow() {
- var stepSelection = ".formStep";
- $(stepSelection).css({
- // height: window.innerHeight - $(stepSelection).offset().top - $('#footerwrap').outerHeight()
- height: window.innerHeight - $(stepSelection).offset().top
- });
- $("fieldset").height(
- $(stepSelection).height() -
- $(stepSelection + ">.stepDesc").height() -
- $(".btn-container").height() -
- 130
- );
- $(".y-scrollable").css({
- // 'max-height': $('fieldset').height()- $('.add-dataset').outerHeight()
- height: $("fieldset").height()
- });
+ updateStep2(body:ProfilingStep2) {
+ this.step2 = body;
+ this.next();
}
- setDropdownList() {
- if (this.selection) {
- for (let item of this.selection) {
- if (item.isNum == true) {
- this.dropdownList[item.name] = [
- { id: 1, itemName: "Null Count", category: "Simple Statistics" },
- { id: 2, itemName: "Distinct Count", category: "Simple Statistics" },
- { id: 3, itemName: "Total Count", category: "Summary Statistics" },
- { id: 4, itemName: "Maximum", category: "Summary Statistics" },
- { id: 5, itemName: "Minimum", category: "Summary Statistics" },
- { id: 6, itemName: "Average", category: "Summary Statistics" },
- // {"id":7,"itemName":"Median","category": "Summary Statistics"},
- // {"id":8,"itemName":"Rule Detection Count","category": "Advanced Statistics"},
- { id: 9, itemName: "Enum Detection Top5 Count", category: "Advanced Statistics" }
- ];
- } else {
- this.dropdownList[item.name] = [
- { id: 1, itemName: "Null Count", category: "Simple Statistics" },
- { id: 2, itemName: "Distinct Count", category: "Simple Statistics" },
- { id: 3, itemName: "Total Count", category: "Summary Statistics" },
- // {"id":8,"itemName":"Rule Detection Count","category": "Advanced Statistics"},
- { id: 9, itemName: "Enum Detection Top5 Count", category: "Advanced Statistics" }
- // {"id":10,"itemName":"Regular Expression Detection Count","category": "Advanced Statistics"}
- ];
+ updateStep3(body:ProfilingStep3) {
+ this.step3 = body;
+ this.next();
+ }
+
+ formValidation = (step) => {
+ if (step == undefined) step = this.currentStep;
+ if (step == 1) {
+ return this.step1.selection && this.step1.selection.length > 0;
+ } else if (step == 2) {
+ let len = 0;
+ let selectedlen = 0;
+ for (let key in this.step2.selectedItems) {
+ selectedlen++;
+ len = this.step2.selectedItems[key].length;
+ if (len == 0) {
+ return false;
}
}
+ return this.step1.selection.length == selectedlen;
+ } else if (step == 3) {
+ return true;
+ } else if (step == 4) {
+ return /^[a-zA-Z0-9_-]+$/.test(this.step4.prName);
}
+ return false;
+ };
+
+ constructor(
+ private elementRef: ElementRef,
+ toasterService: ToasterService,
+ private http: HttpClient,
+ private router: Router,
+ public serviceService: ServiceService
+ ) {
+ this.toasterService = toasterService;
}
- toggleSelection(row) {
- row.selected = !row.selected;
- var idx = this.selection.indexOf(row);
- // is currently selected
- if (idx > -1) {
- this.selection.splice(idx, 1);
- this.selectedAll = false;
- for (let key in this.selectedItems) {
- if (key === row.name) {
- delete this.selectedItems[key];
+ getGrouprule() {
+ var selected = { name: "" };
+ var value = "";
+ var nullvalue = "";
+ var nullname = "";
+ var enmvalue = ""
+ var regexvalue = "";
+ var regexname = "";
+ var grpname = "";
+
+ for (let key in this.step2.selectedItems) {
+ selected.name = key;
+ let info = "";
+ let otherinfo = "";
+ for (let i = 0; i < this.step2.selectedItems[key].length; i++) {
+ var originrule = this.step2.selectedItems[key][i].itemName;
+ info = info + originrule + ",";
+
+ if (originrule == "Enum Detection Top5 Count") {
+
+ enmvalue = this.transferRule(originrule, selected);
+ grpname = `${selected.name}_grp`;
+ this.transenumrule.push(enmvalue);
+ this.pushEnmRule(enmvalue, grpname);
+
+ } else if (originrule == "Null Count") {
+
+ nullvalue = this.transferRule(originrule, selected);
+ nullname = `${selected.name}_nullcount`;
+ this.transnullrule.push(nullvalue);
+ this.pushNullRule(nullvalue, nullname);
+
+ } else if (originrule == "Empty Count") {
+
+ nullvalue = this.transferRule(originrule, selected);
+ nullname = `${selected.name}_emptycount`;
+ this.transnullrule.push(nullvalue);
+ this.pushNullRule(nullvalue, nullname);
+
+ } else if (originrule == "Regular Expression Detection Count") {
+
+ selected['regex'] = this.step2.selectedItems[key].regex;
+ regexvalue = this.transferRule(originrule, selected);
+ regexname = `${selected.name}_regexcount`;
+ this.transregexrule.push(regexvalue);
+ this.pushRegexRule(regexvalue, regexname);
+
+ } else {
+
+ otherinfo = otherinfo + originrule + ",";
+ value = this.transferRule(originrule, selected);
+ this.transrule.push(value);
+
}
}
- } else {
- // is newly selected
- this.selection.push(row);
+
+ info = info.substring(0, info.lastIndexOf(","));
+ otherinfo = otherinfo.substring(0, otherinfo.lastIndexOf(","));
+ this.step4.noderule.push({
+ name: key,
+ infos: info
+ });
}
- if (this.selection.length == 3) {
- this.selectedAll = true;
- } else {
- this.selectedAll = false;
+ if (this.transrule.length != 0) {
+ this.getRule(this.transrule);
}
- this.setDropdownList();
}
- toggleAll() {
- this.selectedAll = !this.selectedAll;
- this.selection = [];
- for (var i = 0; i < this.schemaCollection.length; i++) {
- this.schemaCollection[i].selected = this.selectedAll;
- if (this.selectedAll) {
- this.selection.push(this.schemaCollection[i]);
- }
+ getRule(trans) {
+ var rule = "";
+ for (let i of trans) {
+ rule = rule + i + ",";
}
- this.setDropdownList();
+ rule = rule.substring(0, rule.lastIndexOf(","));
+ this.pushRule(rule);
+ }
+
+ pushEnmRule(rule, grpname) {
+ this.newMeasure["evaluate.rule"].rules.push({
+ "dsl.type": "griffin-dsl",
+ "dq.type": "PROFILING",
+ rule: rule,
+ name: grpname,
+ metric: {
+ "collect.type": "array"
+ }
+ });
+ }
+
+ pushNullRule(rule, nullname) {
+ this.newMeasure["evaluate.rule"].rules.push({
+ "dsl.type": "griffin-dsl",
+ "dq.type": "PROFILING",
+ rule: rule,
+ name: nullname
+ });
+ }
+
+ pushRegexRule(rule, nullname) {
+ this.newMeasure["evaluate.rule"].rules.push({
+ "dsl.type": "griffin-dsl",
+ "dq.type": "PROFILING",
+ rule: rule,
+ name: nullname
+ });
+ }
+
+ pushRule(rule) {
+ this.newMeasure["evaluate.rule"].rules.push({
+ "dsl.type": "griffin-dsl",
+ "dq.type": "PROFILING",
+ rule: rule,
+ name: "profiling"
+ });
}
transferRule(rule, col) {
switch (rule) {
case "Total Count":
- return "count(source.`" + col.name + "`) AS `" + col.name + "-count`";
+ return (
+ `count(source.${col.name}) AS \`${col.name}_count\``
+ );
case "Distinct Count":
return (
- "approx_count_distinct(source.`" +
- col.name +
- "`) AS `" +
- col.name +
- "-distcount`"
+ `approx_count_distinct(source.${col.name}) AS \`${col.name}_distcount\``
);
case "Null Count":
return (
- "count(source.`" +
- col.name +
- "`) AS `" +
- col.name +
- "-nullcount" +
- "` WHERE source.`" +
- col.name +
- "` IS NULL"
+ `count(source.${col.name}) AS \`${col.name}_nullcount\` WHERE source.${col.name} IS NULL`
);
- // case 'Regular Expression Detection Count':
- // return 'count(source.`'+col.name+'`) where source.`'+col.name+'` LIKE ';
- // case 'Rule Detection Count':
- // return 'count(source.`'+col.name+'`) where source.`'+col.name+'` LIKE ';
case "Maximum":
- return "max(source.`" + col.name + "`) AS `" + col.name + "-max`";
+ return (
+ `max(source.${col.name}) AS \`${col.name}_max\``
+ );
case "Minimum":
- return "min(source.`" + col.name + "`) AS `" + col.name + "-min`";
- // case 'Median':
- // return 'median(source.`'+col.name+'`) ';
+ return (
+ `min(source.${col.name}) AS \`${col.name}_min\``
+ );
case "Average":
- return "avg(source.`" + col.name + "`) AS `" + col.name + "-average`";
+ return (
+ `avg(source.${col.name}) AS \`${col.name}_average\``
+ );
+ case "Empty Count":
+ return (
+ `count(source.${col.name}) AS \`${col.name}_emptycount\` WHERE source.${col.name} = ''`
+ );
+ case "Regular Expression Detection Count":
+ return (
+ `count(source.${col.name} RLIKE '${col.regex}') AS \`${col.name}_regexcount\``
+ );
case "Enum Detection Top5 Count":
return (
- "source.`" +
- col.name +
- "`,count(*) AS `" +
- "count` GROUP BY source.`" +
- col.name +
- "` ORDER BY `count` DESC LIMIT 5"
+ `source.${col.name}, ${col.name}, count(*) AS count GROUP BY source.${col.name} ORDER BY count DESC LIMIT 5`
);
}
}
- next(form) {
- if (this.formValidation(this.currentStep)) {
- this.currentStep++;
- } else {
- this.toasterService.pop(
- "error",
- "Error!",
- "Please select at least one attribute!"
- );
- return false;
- }
+ public hide(): void {
+ this.visibleAnimate = false;
+ setTimeout(() => (this.visible = false), 300);
+ this.transrule = [];
+ this.transenumrule = [];
+ this.transnullrule = [];
+ this.transregexrule = [];
+ this.step4.noderule = [];
+ $("#save").removeAttr("disabled");
}
- formValidation = function(step) {
- if (step == undefined) {
- step = this.currentStep;
- }
- if (step == 1) {
- return this.selection && this.selection.length > 0;
- } else if (step == 2) {
- var len = 0;
- var selectedlen = 0;
- for (let key in this.selectedItems) {
- selectedlen++;
- len = this.selectedItems[key].length;
- if (len == 0) {
- return false;
- }
- }
- return this.selection.length == selectedlen ? true : false;
- } else if (step == 3) {
- return true;
- } else if (step == 4) {
+ public onContainerClicked(event: MouseEvent): void {
+ if ((<HTMLElement>event.target).classList.contains("modal")) {
+ this.hide();
}
- return false;
- };
-
- prev(form) {
- this.currentStep--;
- }
- goTo(i) {
- this.currentStep = i;
}
- submit(form) {
- if (!form.valid) {
+
+ submit(body:ProfilingStep4) {
+ this.step4 = body;
+
+ if (!this.formValidation(this.currentStep)) {
this.toasterService.pop(
"error",
"Error!",
- "please complete the form in this step before proceeding"
+ "Please complete the form in this step before proceeding!"
);
return false;
}
+
this.newMeasure = {
- name: this.name,
+ name: this.step4.prName,
"measure.type": "griffin",
"dq.type": "PROFILING",
"rule.description": {
- details:this.noderule
+ details: this.step4.noderule
},
"process.type": "BATCH",
- owner: this.owner,
- description: this.desc,
- // "group":this.finalgrp,
+ owner: this.step4.owner,
+ description: this.step4.desc,
"data.sources": [
{
name: "source",
connectors: [
{
- name: this.srcname,
+ name: this.step1.srcname,
type: "HIVE",
version: "1.2",
- "data.unit": this.size,
- "data.time.zone": this.timezone,
+ "data.unit": this.step3.size,
+ "data.time.zone": this.step3.timezone,
config: {
- database: this.currentDB,
- "table.name": this.currentTable,
- where: this.where
+ database: this.step1.currentDB,
+ "table.name": this.step1.currentTable,
+ where: this.step3.config['where']
},
predicates: [
{
type: "file.exist",
config: {
- "root.path": this.srclocation,
- path: this.path
+ "root.path": this.step1.srclocation,
+ path: this.step3.path
}
}
]
@@ -424,72 +382,26 @@ export class PrComponent implements AfterViewChecked, OnInit {
}
],
"evaluate.rule": {
- rules: [
- // {
- // "dsl.type": "griffin-dsl",
- // "dq.type": "profiling",
- // "rule": "",
- // "details": {}
- // }
- ]
+ rules: []
}
};
+
this.getGrouprule();
- if (this.size.indexOf("0") == 0) {
+ if (this.step3.size.indexOf("0") == 0) {
delete this.newMeasure["data.sources"][0]["connectors"][0]["data.unit"];
}
- if (!this.needpath || this.path == "") {
+ if (!this.step3.needpath || this.step3.path == "") {
delete this.newMeasure["data.sources"][0]["connectors"][0]["predicates"];
}
this.visible = true;
setTimeout(() => (this.visibleAnimate = true), 100);
}
- getRule(trans) {
- var rule = "";
- for (let i of trans) {
- rule = rule + i + ",";
- }
- rule = rule.substring(0, rule.lastIndexOf(","));
- this.pushRule(rule);
- }
-
- pushEnmRule(rule, grpname) {
- var self = this;
- self.newMeasure["evaluate.rule"].rules.push({
- "dsl.type": "griffin-dsl",
- "dq.type": "PROFILING",
- rule: rule,
- name: grpname,
- metric: {
- "collect.type": "array"
- }
- });
- }
-
- pushNullRule(rule, nullname) {
- var self = this;
- self.newMeasure["evaluate.rule"].rules.push({
- "dsl.type": "griffin-dsl",
- "dq.type": "PROFILING",
- rule: rule,
- name: nullname
- });
- }
-
- pushRule(rule) {
- var self = this;
- self.newMeasure["evaluate.rule"].rules.push({
- "dsl.type": "griffin-dsl",
- "dq.type": "PROFILING",
- rule: rule,
- name: "profiling"
- });
- }
-
save() {
- var addModels = this.serviceService.config.uri.addModels;
+ let addModels = this.serviceService.config.uri.addModels;
+
$("#save").attr("disabled", "true");
+
this.http.post(addModels, this.newMeasure).subscribe(
data => {
this.createResult = data;
@@ -508,166 +420,12 @@ export class PrComponent implements AfterViewChecked, OnInit {
);
}
- options: ITreeOptions = {
- displayField: "name",
- isExpandedField: "expanded",
- idField: "id",
- actionMapping: {
- mouse: {
- click: (tree, node, $event) => {
- if (node.hasChildren) {
- this.currentDB = node.data.name;
- this.currentDBstr = this.currentDB + ".";
- this.currentTable = "";
- this.schemaCollection = [];
- this.selectedAll = false;
- TREE_ACTIONS.TOGGLE_EXPANDED(tree, node, $event);
- } else if (node.data.cols) {
- this.currentTable = node.data.name;
- this.currentDB = node.data.parent;
- this.schemaCollection = node.data.cols;
- this.srcname = "source" + new Date().getTime();
- this.srclocation = node.data.location;
- this.selectedAll = false;
- this.selection = [];
- for (let row of this.schemaCollection) {
- row.selected = false;
- }
- }
- }
- }
- },
- animateExpand: true,
- animateSpeed: 30,
- animateAcceleration: 1.2
- };
-
- nodeList: object[];
- nodeListTarget: object[];
-
- constructor(
- private elementRef: ElementRef,
- toasterService: ToasterService,
- private http: HttpClient,
- private router: Router,
- public serviceService: ServiceService
- ) {
- this.toasterService = toasterService;
- this.selection = [];
- }
-
- getGrouprule() {
- var selected = { name: "" };
- var value = "";
- var nullvalue = "";
- var nullname = "";
- var enmvalue = "";
- var grpname = "";
- for (let key in this.selectedItems) {
- selected.name = key;
- var info = "";
- var otherinfo = "";
- for (let i = 0; i < this.selectedItems[key].length; i++) {
- var originrule = this.selectedItems[key][i].itemName;
- info = info + originrule + ",";
- if (originrule == "Enum Detection Top5 Count") {
- enmvalue = this.transferRule(originrule, selected);
- grpname = selected.name + "-grp";
- this.transenumrule.push(enmvalue);
- this.pushEnmRule(enmvalue, grpname);
- } else if (originrule == "Null Count") {
- nullvalue = this.transferRule(originrule, selected);
- nullname = selected.name + "-nullct";
- this.transnullrule.push(nullvalue);
- this.pushNullRule(nullvalue, nullname);
- } else {
- otherinfo = otherinfo + originrule + ",";
- value = this.transferRule(originrule, selected);
- this.transrule.push(value);
- }
- }
- info = info.substring(0, info.lastIndexOf(","));
- otherinfo = otherinfo.substring(0, otherinfo.lastIndexOf(","));
- this.noderule.push({
- name: key,
- infos: info
- });
- }
- if (this.transrule.length != 0) {
- this.getRule(this.transrule);
- }
- this.ruledesc = JSON.stringify(this.noderule);
- }
-
- confirmAdd() {
- document.getElementById("rule").style.display = "none";
- }
-
- showRule() {
- document.getElementById("showrule").style.display = "";
- document.getElementById("notshowrule").style.display = "none";
- }
-
- back() {
- document.getElementById("showrule").style.display = "none";
- document.getElementById("notshowrule").style.display = "";
- }
-
- getData(evt) {
- this.config = evt;
- this.timezone = evt.timezone;
- this.where = evt.where;
- this.size = evt.num + evt.timetype;
- this.needpath = evt.needpath;
- this.path = evt.path;
- }
-
ngOnInit() {
- var allDataassets = this.serviceService.config.uri.dataassetlist;
- this.http.get(allDataassets).subscribe(data => {
- this.nodeList = new Array();
- let i = 1;
- this.data = data;
- for (let db in this.data) {
- let new_node = new node();
- new_node.name = db;
- new_node.id = i;
- new_node.isExpanded = true;
- i++;
- new_node.children = new Array();
- for (let i = 0; i < this.data[db].length; i++) {
- let new_child = new node();
- new_child.name = this.data[db][i]["tableName"];
- new_node.children.push(new_child);
- new_child.isExpanded = false;
- new_child.location = this.data[db][i]["sd"]["location"];
- new_child.parent = db;
- new_child.cols = Array<Col>();
- for (let j = 0; j < this.data[db][i]["sd"]["cols"].length; j++) {
- let new_col = new Col(
- this.data[db][i]["sd"]["cols"][j].name,
- this.data[db][i]["sd"]["cols"][j].type,
- this.data[db][i]["sd"]["cols"][j].comment,
- false
- );
- new_child.cols.push(new_col);
- }
- }
- this.nodeList.push(new_node);
- }
- this.nodeListTarget = JSON.parse(JSON.stringify(this.nodeList));
- });
- this.dropdownSettings = {
- singleSelection: false,
- text: "Select Rule",
- enableCheckAll: false,
- enableSearchFilter: true,
- classes: "myclass",
- groupBy: "category"
- };
- this.size = "1day";
- }
- ngAfterViewChecked() {
- this.resizeWindow();
+ this.step1 = new ProfilingStep1();
+ this.step2 = new ProfilingStep2();
+ this.step3 = new ProfilingStep3();
+ this.step4 = new ProfilingStep4();
}
+
+ ngAfterViewChecked() {}
}
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/step1/step1.component.css
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/step1/step1.component.css b/ui/angular/src/app/measure/create-measure/pr/step1/step1.component.css
new file mode 100644
index 0000000..fd725f8
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/step1/step1.component.css
@@ -0,0 +1,141 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+
+@import url('../../../../../../node_modules/angular2-toaster/toaster.css');
+@import url('../../../measure.component.css');
+
+fieldset {
+ height: 60vh;
+}
+
+label.stepDesc {
+ padding-left: 30px;
+ padding-right: 30px;
+}
+
+div.btn-container {
+ width: 100%;
+ padding-left: 30px;
+ padding-right: 30px;
+ clear: both;
+}
+
+div.tree div.tree-children::before,
+div.tree::before {
+ content: "";
+ position: absolute;
+ border-left: 1px dotted #23527c;
+ height: 100%;
+ top: -14px;
+ left: 12px
+}
+
+tree-root {
+ color: #999;
+}
+
+div.tree {
+ padding-left: 0;
+ margin-left: -5px
+}
+
+div.tree div.tree-children {
+ position: relative;
+ padding-left: 0;
+ margin-left: 16px
+}
+
+div.tree div.tree-children::before {
+ left: 5px
+}
+
+div.tree treenode>div>.node-wrapper {
+ margin-left: 24px
+}
+
+div.tree treenode>div>.node-wrapper>.node-content-wrapper {
+ margin-left: 4px
+}
+
+div.tree treenode>div.tree-node-leaf>.node-wrapper {
+ margin-left: 0
+}
+
+div.tree treenode>div::before {
+ content: "";
+ position: absolute;
+ border-bottom: 1px dotted #23527c;
+ width: 7px;
+ margin-top: 12px;
+ left: 7px
+}
+
+div.tree treenode>div .toggle-children-wrapper {
+ width: 13px;
+ height: 13px;
+ border: 1px solid #23527c;
+ position: absolute;
+ left: 15px;
+ margin-top: 5px;
+ margin-left: 0;
+ display: inline-block;
+ background-color: #fff;
+ z-index: 1
+}
+
+div.tree treenode>div .toggle-children-wrapper::before {
+ content: "";
+ display: inline-block;
+ width: 7px;
+ border-top: 1px solid #23527c;
+ position: absolute;
+ top: 5px;
+ left: 2px
+}
+
+div.tree treenode>div .toggle-children-wrapper.toggle-children-wrapper-collapsed::after {
+ content: "";
+ display: inline-block;
+ height: 7px;
+ border-left: 1px solid #23527c;
+ position: absolute;
+ top: 2px;
+ left: 5px
+}
+
+div.tree treenode>div .toggle-children-wrapper .toggle-children {
+ display: none
+}
+
+div.tree treenode>div .node-content-wrapper {
+ margin-left: 4px
+}
+
+div.tree>treenode>div::before {
+ left: 14px
+}
+
+div.tree>treenode>div>.node-wrapper>treenodeexpander>.toggle-children-wrapper {
+ left: 22px
+}
+
+table > tbody > tr > td, .table > thead > tr > th {
+ word-wrap: break-word;
+ min-width: 80px;
+}
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/step1/step1.component.html
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/step1/step1.component.html b/ui/angular/src/app/measure/create-measure/pr/step1/step1.component.html
new file mode 100644
index 0000000..4c9eb99
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/step1/step1.component.html
@@ -0,0 +1,78 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<div class="container-fluid">
+ <form name="Form" id="form" #prForm="ngForm" novalidate>
+ <label class="stepDesc">This step lets you select the single source of truth for data quality comparision with a target source.</label>
+ <div class="container-fluid">
+ <div class="col-md-4 col-lg-4 col-sm-4">
+ <fieldset>
+ <legend>Please select schema</legend>
+ <tree-root [nodes]="step1.nodeList" [options]="options"></tree-root>
+ </fieldset>
+ </div>
+ <div class="col-md-8 col-lg-8 col-sm-8">
+ <fieldset>
+ <legend>
+ Select attributes
+ </legend>
+ <div class="y-scrollable">
+ <div style="margin-top:10px;">
+ <label>View schema:</label>
+ <i style="color:#fff;font-weight: bold;">{{step1.currentDBstr}}{{step1.currentTable}}
+ </i>
+ </div>
+ <div style="margin-top:5px;">
+ <table class="table table-striped no-border">
+ <thead>
+ <tr style="background-color:#7D95CC">
+ <th>
+ <input type="checkbox" (click)="toggleAll()" [checked]="selectedAll" />
+ </th>
+ <th>Column Name</th>
+ <th>Type</th>
+ <th>Comment</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr *ngIf="!step1.schemaCollection || step1.schemaCollection.length == 0">
+ <td colspan="5" style="text-align:center;"><span class="highlight">Please select a schema from the left tree first</span></td>
+ </tr>
+ <tr *ngFor="let row of step1.schemaCollection">
+ <td>
+ <input type="checkbox" (click)='toggleSelection(row)' [checked]="row.selected" value={{row.name}} />
+ </td>
+ <td>{{row.name}}</td>
+ <td>{{row.type}}</td>
+ <td>{{row.comment}}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
+ </fieldset>
+ </div>
+ </div>
+ </form>
+
+ <div class="form-group btn-container">
+ <button class="btn btn-primary btn-o next-step btn-wide pull-right" (click)="nextChildStep()">
+ Next <i class="fa fa-arrow-circle-right"></i>
+ </button>
+ </div>
+</div>
http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/d58bd194/ui/angular/src/app/measure/create-measure/pr/step1/step1.component.spec.ts
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pr/step1/step1.component.spec.ts b/ui/angular/src/app/measure/create-measure/pr/step1/step1.component.spec.ts
new file mode 100644
index 0000000..13d47d4
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pr/step1/step1.component.spec.ts
@@ -0,0 +1,43 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+*/
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { PrStep1Component } from './step1.component';
+
+describe('PrStep1Component', () => {
+ let component: PrStep1Component;
+ let fixture: ComponentFixture<PrStep1Component>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [ PrStep1Component ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(PrStep1Component);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should be created', () => {
+ expect(component).toBeTruthy();
+ });
+});