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/04/09 04:02:07 UTC

incubator-griffin git commit: [GRIFFIN-121] UI-JIRA- Add publish measure create process on UI

Repository: incubator-griffin
Updated Branches:
  refs/heads/master 5255d71c7 -> 2aa58c0b3


[GRIFFIN-121] UI-JIRA- Add publish measure create process on UI

UI-JIRA-GRIFFIN-121 Add publish measure create process on UI

Author: jenny <su...@gmail.com>

Closes #246 from icesmartjuan/ui_addpublish.


Project: http://git-wip-us.apache.org/repos/asf/incubator-griffin/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-griffin/commit/2aa58c0b
Tree: http://git-wip-us.apache.org/repos/asf/incubator-griffin/tree/2aa58c0b
Diff: http://git-wip-us.apache.org/repos/asf/incubator-griffin/diff/2aa58c0b

Branch: refs/heads/master
Commit: 2aa58c0b3e94f4c778f749bb6b8d80c48fbd0060
Parents: 5255d71
Author: jenny <su...@gmail.com>
Authored: Mon Apr 9 12:02:00 2018 +0800
Committer: Lionel Liu <bh...@163.com>
Committed: Mon Apr 9 12:02:00 2018 +0800

----------------------------------------------------------------------
 .../core/measure/entity/ExternalMeasure.java    |   2 +-
 ui/angular/src/app/app.module.ts                |   6 +
 ui/angular/src/app/health/health.component.ts   |   5 +-
 .../create-measure.component.html               |  31 ++
 .../create-measure/pub/pub.component.css        | 506 +++++++++++++++++++
 .../create-measure/pub/pub.component.html       | 211 ++++++++
 .../create-measure/pub/pub.component.spec.ts    |  43 ++
 .../measure/create-measure/pub/pub.component.ts | 216 ++++++++
 .../measure-detail.component.html               |   8 +
 .../measure-detail/measure-detail.component.ts  |   1 +
 .../src/app/measure/measure.component.css       |  12 +
 ui/angular/src/app/metric/metric.component.html |   9 +-
 ui/angular/src/app/metric/metric.component.ts   |   3 +-
 ui/angular/src/app/sidebar/sidebar.component.ts |   3 +-
 14 files changed, 1044 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/2aa58c0b/service/src/main/java/org/apache/griffin/core/measure/entity/ExternalMeasure.java
----------------------------------------------------------------------
diff --git a/service/src/main/java/org/apache/griffin/core/measure/entity/ExternalMeasure.java b/service/src/main/java/org/apache/griffin/core/measure/entity/ExternalMeasure.java
index 2339df0..b6a9f0b 100644
--- a/service/src/main/java/org/apache/griffin/core/measure/entity/ExternalMeasure.java
+++ b/service/src/main/java/org/apache/griffin/core/measure/entity/ExternalMeasure.java
@@ -43,7 +43,7 @@ public class ExternalMeasure extends Measure {
         super();
     }
 
-    public ExternalMeasure(String name, String description, String organization, String owner, String metricName,VirtualJob vj) {
+    public ExternalMeasure(String name, String description, String organization, String owner, String metricName, VirtualJob vj) {
         super(name, description, organization, owner);
         this.metricName = metricName;
         this.virtualJob = vj;

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/2aa58c0b/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 7a26d6a..d2b5995 100644
--- a/ui/angular/src/app/app.module.ts
+++ b/ui/angular/src/app/app.module.ts
@@ -42,6 +42,7 @@ import { DataassetComponent } from './dataasset/dataasset.component';
 import { CreateJobComponent } from './job/create-job/create-job.component';
 import { AcComponent} from './measure/create-measure/ac/ac.component';
 import { PrComponent } from './measure/create-measure/pr/pr.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';
 import { RuleComponent } from './measure/create-measure/pr/rule/rule.component';
@@ -89,6 +90,10 @@ const appRoutes: Routes = [
     component:PrComponent
   },
   {
+    path: 'createmeasurepub',
+    component:PubComponent
+  },
+  {
     path: 'detailed/:name',
     component:DetailMetricComponent
   },
@@ -132,6 +137,7 @@ const appRoutes: Routes = [
     CreateJobComponent,
     AcComponent,
     PrComponent,
+    PubComponent,
     LoginComponent,
     RuleComponent,
     TruncatePipe,

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/2aa58c0b/ui/angular/src/app/health/health.component.ts
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/health/health.component.ts b/ui/angular/src/app/health/health.component.ts
index bbba430..622a0ec 100644
--- a/ui/angular/src/app/health/health.component.ts
+++ b/ui/angular/src/app/health/health.component.ts
@@ -175,8 +175,7 @@ export class HealthComponent implements OnInit {
       for (let mesName in this.mesWithJob) {
         var metricData = this.mesWithJob[mesName][0];
         if (
-          metricData.metricValues[0] != undefined &&
-          metricData.type == "accuracy"
+          metricData.metricValues[0] != undefined && metricData.type == "accuracy"
         ) {
           var jobs = this.mesWithJob[mesName];
           var node = null;
@@ -196,7 +195,7 @@ export class HealthComponent implements OnInit {
               metricNode.details = JSON.parse(
                 JSON.stringify(jobs[i].metricValues)
               );
-              metricNode.name = jobs[i].name;
+              metricNode.name = mesName; //jobs[i].name;// to avoid same metricName
               metricNode.timestamp = jobs[i].metricValues[0].tmst;
               metricNode.dq =
                 jobs[i].metricValues[0].value.matched /

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/2aa58c0b/ui/angular/src/app/measure/create-measure/create-measure.component.html
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/create-measure.component.html b/ui/angular/src/app/measure/create-measure/create-measure.component.html
index ab9909b..c3aa6a9 100644
--- a/ui/angular/src/app/measure/create-measure/create-measure.component.html
+++ b/ui/angular/src/app/measure/create-measure/create-measure.component.html
@@ -148,6 +148,37 @@ under the License.
         </div>
       </section>
     </div>
+    <div class="col-lg-6 col-md-6 col-sm-6 ruletypes">
+      <section id="panel-3" class="panel panel-green" (click)="click('pub')">
+        <div class="panel-heading">
+          <span style="font-size:20px">Publish</span>
+          <span class="pull-right" style="font-size:20px">
+                  <span class="fa fa-arrow-circle-right"></span>
+          </span>
+        </div>
+        <div class="swMain panel-body">
+          <label class="label-definition">Definition: Publish is the process of storing user's own quality data and visualizing it</label>
+          <ul style="border-radius:0; background: none">            
+            <li>
+              <div class="selected1child" style="cursor:default">
+                <div class="stepNumber">
+                  1
+                </div>
+                <span class="stepDesc text-small"> Configuration </span>
+              </div>
+            </li>
+          </ul>
+          <div>
+            <ol>              
+              <li>Set basic configuration for your model(name, system, threshold, etc.)</li>
+            </ol>
+          </div>
+        </div>
+        <div class="panel-footer stepDesc">
+          <label>Example: any data</label> ...
+        </div>
+      </section>
+    </div>
   </div>
   <!--//row-->
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/2aa58c0b/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
new file mode 100644
index 0000000..194a251
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pub/pub.component.css
@@ -0,0 +1,506 @@
+/*
+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'); */
+
+.selected-list .c-list .c-token {
+  background: #6faece;
+}
+
+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
+}
+
+label {
+  font-weight: normal;
+}
+
+.container {
+  max-height: 40vh;
+  overflow-y: scroll;
+}
+
+/*
+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.
+*/
+
+.table-striped>tbody>tr:nth-of-type(even) {
+  background-color: #1f1f1f;
+}
+
+.table-striped>tbody>tr:nth-of-type(odd) {
+  background-color: #080808;
+}
+
+.icon {
+  color: #fff;
+  position: absolute;
+  left: 50%;
+  top: 20%;
+}
+
+#measureTable {
+  font-size: 18px;
+}
+
+.po {
+  cursor: pointer;
+}
+
+.ng2-st-actions-title .ng2-smart-title {
+  color: #1e6bb8;
+}
+
+#measureTable .ng2-smart-titles {
+  background-color: #7D95CC;
+}
+
+.pagination>li>a {
+  cursor: pointer;
+}
+
+.swMain>ul {
+  display: table;
+  list-style: none;
+  margin: 0 0 20px;
+  padding: 10px 0;
+  position: relative;
+  width: 100%;
+  background: #f7f7f8;
+  border-radius: 5px
+}
+
+.formStep {
+  background-color: #000000;
+  border-radius: 5px;
+  padding: 10px;
+  /*height:800px;*/
+}
+
+.swMain>ul li {
+  display: table-cell;
+  text-align: center;
+  width: 1%
+}
+
+.swMain>ul li>a:before {
+  border-top: 4px solid #c8c7cc;
+  /* content: ""; */
+  display: block;
+  font-size: 0;
+  height: 1px;
+  overflow: hidden;
+  position: relative;
+  top: 21px;
+  width: 100%;
+  z-index: 1
+}
+
+.onlyone:before {
+  left: 0 !important;
+  max-width: 100% !important;
+  width: 100% !important;
+}
+
+.swMain>ul .stepNumber {
+  background-color: #fff;
+  border: 5px solid #c8c7cc;
+  border-radius: 100%;
+  color: #546474;
+  display: inline-block;
+  font-size: 15px;
+  height: 40px;
+  line-height: 30px;
+  position: relative;
+  text-align: center;
+  width: 40px;
+  z-index: 2
+}
+
+.swMain>ul li>a.selected .stepNumber {
+  border-color: #007AFF
+}
+
+.swMain ul li>a.done .stepNumber {
+  border-color: #007AFF;
+  background-color: #007AFF;
+  color: #fff;
+  text-indent: -9999px
+}
+
+.swMain ul li>a.done .stepNumber:before {
+  content: "\f00c";
+  display: inline;
+  float: right;
+  font-family: FontAwesome;
+  font-weight: 300;
+  height: auto;
+  text-shadow: none;
+  margin-right: 7px;
+  text-indent: 0
+}
+
+.swMain ul li>a.done.wait .stepNumber {
+  background-color: #F6F6F6!important;
+  color: #CCC!important;
+  text-indent: 0!important
+}
+
+.swMain ul li>a.done.wait .stepNumber:before {
+  content: ""!important
+}
+
+.swMain>ul li .stepDesc {
+  color: #8e8e93;
+  display: block;
+  font-size: 14px;
+  margin-top: 4px;
+  max-width: 100%;
+  table-layout: fixed;
+  text-align: center;
+  word-wrap: break-word;
+  z-index: 104
+}
+
+.swMain li>a.done .stepDesc,
+.swMain>ul li>a.selected .stepDesc {
+  /*color: #2B3D53*/
+  color: #007AFF
+}
+
+.swMain>ul li>a.disabled {
+  cursor: default
+}
+
+.swMain .progress {
+  margin-bottom: 30px
+}
+
+.swMain .stepContainer {
+  height: auto!important
+}
+
+.swMain .y-scrollable {
+  overflow-y: auto;
+  overflow-x: hidden;
+  max-height: 600px;
+}
+
+fieldset {
+  border: 1px solid #e6e8e8;
+  border-radius: 5px;
+  margin: 20px 0;
+  padding: 25px;
+  position: relative;
+  min-width: 0;
+  display: block;
+}
+
+fieldset legend {
+  background-color: #000000;
+  left: 10px;
+  padding: 0 10px;
+  position: absolute;
+  top: -12px;
+  color: #fff;
+  font-weight: 400;
+  width: auto!important;
+  border: none!important;
+}
+
+.btn-o {
+  background: 0 0!important;
+}
+
+.btn-wide {
+  min-width: 120px;
+}
+
+.highlight {
+  background: rgba(255, 230, 0, 0.5);
+  padding: 3px 5px;
+  margin: -3px -5px;
+  line-height: 1.7;
+  word-break: break-word;
+  /*border-radius: 3px;*/
+  /*display:inline-block;*/
+}
+
+.label-definition {
+  color: #fff;
+}
+
+.formStep>.stepDesc {
+  color: #b2c831;
+}
+
+.formStep>.container-fluid {
+  /*position:relative;*/
+}
+
+.btn-container {
+  height: 50px;
+  /*position: absolute;
+  bottom: 10;*/
+}
+
+.panel-disabled {
+  border-color: #B9D3DF;
+}
+
+.panel-disabled>.panel-heading {
+  background-color: #B9D3DF;
+  border-color: #B9D3DF;
+}
+
+.panel-body>ul {
+  border-radius: 0;
+  background: none;
+  margin: 0;
+}
+
+
+.panel-green {
+  border-color: #5cb85c;
+}
+
+.panel-green .panel-heading {
+  border-color: #5cb85c;
+  color: #fff;
+  background-color: #5cb85c;
+}
+
+.panel-green a {
+  color: #5cb85c;
+}
+
+.panel-green a:hover {
+  color: #3d8b3d;
+}
+
+.panel-red {
+  border-color: #d9534f;
+}
+
+.panel-red .panel-heading {
+  border-color: #d9534f;
+  color: #fff;
+  background-color: #d9534f;
+}
+
+.panel-red a {
+  color: #d9534f;
+}
+
+.panel-red a:hover {
+  color: #b52b27;
+}
+
+.panel-yellow {
+  border-color: #f0ad4e;
+}
+
+.panel-yellow .panel-heading {
+  border-color: #f0ad4e;
+  color: #fff;
+  background-color: #f0ad4e;
+}
+
+.panel-yellow a {
+  color: #f0ad4e;
+}
+
+.panel-yellow a:hover {
+  color: #df8a13;
+}
+
+.viewrule-content {
+  border: 1px solid #fff;
+  border-radius: 4px;
+  padding: 10px;
+}
+
+.ruletypes>.panel {
+  cursor: pointer
+}
+
+.ruletypes>.panel:hover {
+  box-shadow: 3px 3px 5px 6px #ccc;
+  /* Opera 10.5, IE 9, Firefox 4+, Chrome 6+, iOS 5 */
+  -webkit-box-shadow: 3px 3px 5px 6px #ccc;
+  /* Safari 3-4, iOS 4.0.2 - 4.2, Android 2.3+ */
+  -moz-box-shadow: 3px 3px 5px 6px #ccc;
+  /* Firefox 3.5 - 3.6 */
+}
+
+.createrule-hint {
+  color: #b2c831;
+  padding-top: 10px;
+}
+
+
+::-webkit-scrollbar {
+  width: 6px;
+}
+
+::-webkit-scrollbar-track {
+  background-color: #eaeaea;
+  /*background-color: #0a0a0a;*/
+  border-left: 1px solid #ccc;
+}
+
+::-webkit-scrollbar-thumb {
+  background-color: #ccc;
+}
+
+::-webkit-scrollbar-thumb:hover {
+  background-color: #aaa;
+}
+
+.disabled {
+  pointer-events: none;
+  cursor: default;
+  opacity: 0.6;
+}
+
+.test-result {
+  border-radius: 5px;
+  padding: 1px 5px;
+}
+
+.delete-alert {
+  text-align: left;
+  color: white;
+  font-size: 150%;
+}
+
+a {
+  color: white;
+}

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/2aa58c0b/ui/angular/src/app/measure/create-measure/pub/pub.component.html
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pub/pub.component.html b/ui/angular/src/app/measure/create-measure/pub/pub.component.html
new file mode 100644
index 0000000..b6e847f
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pub/pub.component.html
@@ -0,0 +1,211 @@
+<!--
+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" (window:resize)="onResize($event)">
+  <div class="row">
+    <h5 class="over-title margin-bottom-15">Create Measure</h5>
+  </div>
+  <div class="row">
+    <form name="Form" id="form" #prForm="ngForm" novalidate>
+      <div id="wizard" class="swMain">
+        <ul> 
+          <li>
+            <a class="selected">
+              <div class="stepNumber">
+                1
+              </div>
+              <span class="stepDesc text-small"> Configuration </span>
+            </a>
+          </li>
+        </ul>
+      </div>  
+      <div id="step-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)]="newMeasure.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" [ngClass]="{'has-error':mName.dirty&&mName.invalid, 'has-success':mName.valid}">
+                    <label class="col-md-2 col-lg-2 col-sm-2 control-label">
+                      Metric 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)]="newMeasure.metricName" #mName="ngModel" name="mName" placeholder="Please input the metric name" required pattern="^[a-zA-Z0-9_-]*$">
+                      <span class="error text-small block " *ngIf="mName.dirty && (mName.errors?.required)">Metric Name is required</span>
+                      <span class="error text-small block " *ngIf="mName.dirty && (mName.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" [ngClass]="{'has-error':mName.dirty&&mName.invalid, 'has-success':mName.valid}">
+                    <label class="col-md-2 col-lg-2 col-sm-2 control-label">
+                      Dq Type<span class="symbol required"></span>:
+                    </label>
+                    <div class="col-md-10 col-lg-10 col-sm-10 ">
+                      <select [(ngModel)]="newMeasure.dqType" name="dqTypeOptions[{{i}}]"  class="form-control input-sm" placeholder="Visual Type" required>
+                       <option *ngFor="let t of dqTypeOptions" value="{{t}}">{{t}}</option>
+                      </select>  
+                      <span class="error text-small block " *ngIf="mName.dirty && (mName.errors?.required)">Metric Name 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">
+                      Measure Description:
+                    </label>
+                    <div class="col-md-10 col-lg-10 col-sm-10 ">
+                      <input type="text" class="form-control" [(ngModel)]="newMeasure.description" 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:
+                    </label>
+                    <div class="col-md-10 col-lg-10 col-sm-10 ">
+                      <select id="typeSelector" class="form-control" [(ngModel)]="newMeasure.measureType" disabled required name="type">
+                        <option>{{newMeasure.measureType}}</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">
+                      Owner:
+                    </label>
+                    <div class="col-md-10 col-lg-10 col-sm-10">
+                      <input type="text" class="form-control" name="owner" disabled [(ngModel)]="newMeasure.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>
+      </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()">&times;</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 ">
+                          {{newMeasure.name}}
+                        </div>
+                      </div>
+                      <div class="row">
+                        <label class="col-md-4 col-lg-4 col-sm-4">
+                          Metric Name:
+                        </label>
+                        <div class="col-md-8 col-lg-8 col-sm-8 ">
+                          {{newMeasure.metricName}}
+                        </div>
+                      </div>
+                      <div class="row">
+                        <label class="col-md-4 col-lg-4 col-sm-4">
+                          Dq Type:
+                        </label>
+                        <div class="col-md-8 col-lg-8 col-sm-8 ">
+                          {{newMeasure.dqType}}
+                        </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 ">
+                          {{newMeasure.description}}
+                        </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 ">
+                          {{newMeasure.measureType}}
+                        </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">
+                          {{newMeasure.owner}}
+                        </div>
+                      </div>
+                    </div>
+                  </div>
+                </div>                
+              </div>
+            </div>
+            <div class="modal-footer">
+              <button type="button" class="btn btn-default" (click)="hide()">Cancel</button>
+              <button type="button" class="btn btn-primary" (click)="save()">Save</button>
+            </div>
+          </div>
+        </div>
+      </div>
+    </form>
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/2aa58c0b/ui/angular/src/app/measure/create-measure/pub/pub.component.spec.ts
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pub/pub.component.spec.ts b/ui/angular/src/app/measure/create-measure/pub/pub.component.spec.ts
new file mode 100644
index 0000000..0b74802
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pub/pub.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 { PubComponent } from './pub.component';
+
+describe('PrComponent', () => {
+  let component: PubComponent;
+  let fixture: ComponentFixture<PubComponent>;
+
+  beforeEach(async(() => {
+    TestBed.configureTestingModule({
+      declarations: [ PubComponent ]
+    })
+    .compileComponents();
+  }));
+
+  beforeEach(() => {
+    fixture = TestBed.createComponent(PubComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should be created', () => {
+    expect(component).toBeTruthy();
+  });
+});

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/2aa58c0b/ui/angular/src/app/measure/create-measure/pub/pub.component.ts
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/create-measure/pub/pub.component.ts b/ui/angular/src/app/measure/create-measure/pub/pub.component.ts
new file mode 100644
index 0000000..99871eb
--- /dev/null
+++ b/ui/angular/src/app/measure/create-measure/pub/pub.component.ts
@@ -0,0 +1,216 @@
+/*
+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 } 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";
+
+interface pubMeasure {
+  name: string;
+  metricName: string;
+  description: string;
+  measureType: string;
+  dqType: string;
+  owner: string
+}
+export function createPubMeasure(name: string,
+  metricName: string,
+  description: string,
+  measureType: string,
+  dqType: string,
+  owner: string) {
+  return {
+    name,
+    metricName,
+    description,
+    measureType,
+    dqType,
+    owner
+  }
+}
+@Component({
+  selector: "app-pub",
+  templateUrl: "./pub.component.html",
+  providers: [ServiceService],
+  styleUrls: ["./pub.component.css"]
+})
+export class PubComponent implements AfterViewChecked, OnInit {    
+  newMeasure = createPubMeasure("", "", "","external","accuracy","test"); 
+  dqTypeOptions =["accuracy"];
+  createResult: any;
+  private toasterService: ToasterService;
+  public visible = false;
+  public visibleAnimate = false;
+
+  public hide(): void {
+    this.visibleAnimate = false;
+    setTimeout(() => (this.visible = false), 300);
+  }
+
+  public onContainerClicked(event: MouseEvent): void {
+    if ((<HTMLElement>event.target).classList.contains("modal")) {
+      this.hide();
+    }
+  }
+
+  onResize(event) {
+    this.resizeWindow();
+  }
+
+  resizeWindow() {
+    var stepSelection = ".formStep";
+    $(stepSelection).css({
+      height: window.innerHeight - $(stepSelection).offset().top
+    });
+    $("fieldset").height(
+      $(stepSelection).height() -
+        $(stepSelection + ">.stepDesc").height() -
+        $(".btn-container").height() -
+        130
+    );
+    $(".y-scrollable").css({
+      height: $("fieldset").height()
+    });
+  }
+
+
+  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) {
+    }
+    return false;
+  };
+
+  submit(form) {
+    if (!form.valid) {
+      this.toasterService.pop(
+        "error",
+        "Error!",
+        "please complete the form in this step before proceeding"
+      );
+      return false;
+    }
+    this.visible = true;
+    setTimeout(() => (this.visibleAnimate = true), 100);
+  }
+
+  
+
+  save() {     
+    var measure2Save ={
+      name:this.newMeasure.name,
+      metricName: this.newMeasure.metricName,
+      "measure.type":this.newMeasure.measureType,
+      description:this.newMeasure.description,
+      "dq.type":this.newMeasure.dqType,
+      owner:this.newMeasure.owner
+    }
+    var addModels = this.serviceService.config.uri.addModels;
+    this.http.post(addModels, measure2Save).subscribe(
+      data => {
+        this.createResult = data;
+        this.hide();
+        this.router.navigate(["/measures"]);
+      },
+      err => {
+        let response = JSON.parse(err.error);
+        if(response.code === '40901'){
+          this.toasterService.pop("error", "Error!", "Measure name already exists!");
+        } else {
+          this.toasterService.pop("error", "Error!", "Error when creating measure");
+        }
+        console.log("Error when creating measure");
+      }
+    );
+  }
+
+  options: ITreeOptions = {
+    displayField: "name",
+    isExpandedField: "expanded",
+    idField: "id",
+    actionMapping: {
+      mouse: {
+        click: (tree, node, $event) => {
+          if (node.hasChildren) {
+            
+            TREE_ACTIONS.TOGGLE_EXPANDED(tree, node, $event);
+          } else if (node.data.cols) {
+           
+            
+          }
+        }
+      }
+    },
+    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;
+  }
+
+  ngOnInit() {
+    var allDataassets = this.serviceService.config.uri.dataassetlist;
+    this.http.get(allDataassets).subscribe(data => {
+      this.nodeList = new Array();
+      
+    });
+    
+  }
+  ngAfterViewChecked() {
+    this.resizeWindow();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/2aa58c0b/ui/angular/src/app/measure/measure-detail/measure-detail.component.html
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/measure-detail/measure-detail.component.html b/ui/angular/src/app/measure/measure-detail/measure-detail.component.html
index e6ccacb..fc7d1df 100644
--- a/ui/angular/src/app/measure/measure-detail/measure-detail.component.html
+++ b/ui/angular/src/app/measure/measure-detail/measure-detail.component.html
@@ -48,6 +48,14 @@ under the License.
             {{ruleData.type}}
           </div>
         </div>
+        <div class="row" *ngIf="ruleData.dqType">
+          <label class="col-xs-4">
+            Dq Type:
+          </label>
+          <div class="col-xs-8 " style="color: #fff">
+            {{ruleData.dqType}}
+          </div>
+        </div>
         <div class="row" *ngIf="ruleData.type=='accuracy'">
           <label class="col-xs-4">
             Source:

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/2aa58c0b/ui/angular/src/app/measure/measure-detail/measure-detail.component.ts
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/measure/measure-detail/measure-detail.component.ts b/ui/angular/src/app/measure/measure-detail/measure-detail.component.ts
index 42c41af..56d982a 100644
--- a/ui/angular/src/app/measure/measure-detail/measure-detail.component.ts
+++ b/ui/angular/src/app/measure/measure-detail/measure-detail.component.ts
@@ -85,6 +85,7 @@ export class MeasureDetailComponent implements OnInit {
         this.ruleData = data;
         if (this.ruleData["measure.type"] === "external") {
           this.ruleData.type = this.ruleData["measure.type"];
+          this.ruleData.dqType = this.ruleData["dq.type"];
         } else{
           this.ruleData.type = this.ruleData["dq.type"];
           this.currentrule = this.ruleData["evaluate.rule"].rules;

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/2aa58c0b/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 d9218f6..7381878 100644
--- a/ui/angular/src/app/measure/measure.component.css
+++ b/ui/angular/src/app/measure/measure.component.css
@@ -385,3 +385,15 @@ fieldset legend {
 a {
   color: white;
 }
+
+.swMain li>div.done .stepDesc,
+.swMain>ul li>div.selected1child .stepDesc {
+  color: #007AFF
+}
+.swMain li>div.done:before,
+.swMain>ul li>div.selected1child:before {
+  border-color: #007AFF
+}
+.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/2aa58c0b/ui/angular/src/app/metric/metric.component.html
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/metric/metric.component.html b/ui/angular/src/app/metric/metric.component.html
index bab752c..52023ca 100644
--- a/ui/angular/src/app/metric/metric.component.html
+++ b/ui/angular/src/app/metric/metric.component.html
@@ -29,14 +29,15 @@ under the License.
 	    </span>
       </div>
     </div>
-    <div *ngFor="let outerItems of finalData;let parent=index">
-      <div class="row">
-        <div class="col-sm-12 col-md-12 col-lg-12">
+    <div class="col-sm-5 chartItem"  *ngFor="let outerItems of finalData;let parent=index" style="margin-bottom:30px;margin-right:15px;">
+      <div class="row">      
+        <div style="text-align: center;" >
           <h4>{{outerItems.name}}</h4>
         </div>
       </div>
       <div class="row">
-        <div class="col-sm-6 col-md-4 col-xs-12 col-lg-3 chartItem" *ngFor="let items of outerItems.metrics;let i=index;" style="margin-bottom:30px;">
+        <!-- <div class="col-sm-6 col-md-4 col-xs-12 col-lg-3 chartItem" *ngFor="let items of outerItems.metrics;let i=index;" style="margin-bottom:30px;"> -->
+          <div *ngFor="let items of outerItems.metrics;let i=index;">
           <div class="row-fluid" style="cursor: pointer;">
             <div id="thumbnail{{parent}}-{{i}}" class="thumb-chart" style="border: 2px solid;" echarts [options]="getOption(parent,i)" (click)="goTo(parent,i)"></div>
           </div>

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/2aa58c0b/ui/angular/src/app/metric/metric.component.ts
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/metric/metric.component.ts b/ui/angular/src/app/metric/metric.component.ts
index 7df1f84..63bc8ae 100644
--- a/ui/angular/src/app/metric/metric.component.ts
+++ b/ui/angular/src/app/metric/metric.component.ts
@@ -57,8 +57,7 @@ export class MetricComponent implements OnInit {
       for (let mesName in this.mesWithJob) {
         var metricData = this.mesWithJob[mesName][0];
         if (
-          metricData.metricValues[0] != undefined &&
-          metricData.type == "accuracy"
+          metricData.metricValues[0] != undefined && metricData.type == "accuracy"
         ) {
           var jobs = this.mesWithJob[mesName];
           var node = null;

http://git-wip-us.apache.org/repos/asf/incubator-griffin/blob/2aa58c0b/ui/angular/src/app/sidebar/sidebar.component.ts
----------------------------------------------------------------------
diff --git a/ui/angular/src/app/sidebar/sidebar.component.ts b/ui/angular/src/app/sidebar/sidebar.component.ts
index 30ae045..8a6fef5 100644
--- a/ui/angular/src/app/sidebar/sidebar.component.ts
+++ b/ui/angular/src/app/sidebar/sidebar.component.ts
@@ -105,8 +105,7 @@ export class SidebarComponent implements OnInit {
       for (let mesName in this.mesWithJob) {
         var metricData = this.mesWithJob[mesName][0];
         if (
-          metricData.metricValues[0] != undefined &&
-          metricData.type == "accuracy"
+         metricData.metricValues[0] != undefined && metricData.type == "accuracy"
         ) {
           var jobs = this.mesWithJob[mesName];
           var node = null;