You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by ma...@apache.org on 2015/05/15 07:22:02 UTC

[33/52] [abbrv] incubator-kylin git commit: validation on cube submit

validation on cube submit


Project: http://git-wip-us.apache.org/repos/asf/incubator-kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-kylin/commit/992fd74f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-kylin/tree/992fd74f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-kylin/diff/992fd74f

Branch: refs/heads/0.8.0
Commit: 992fd74fb599e2452232ad7c80670c99c1e29d70
Parents: 3754d62
Author: jiazhong <ji...@ebay.com>
Authored: Tue Mar 31 19:45:12 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:53 2015 +0800

----------------------------------------------------------------------
 webapp/app/js/controllers/cubeDimensions.js     |  65 ++-
 webapp/app/js/controllers/cubeEdit.js           |  14 +-
 webapp/app/js/controllers/cubeSchema.js         |  79 ++-
 webapp/app/js/controllers/job.js                |   7 +-
 webapp/app/js/controllers/modelEdit.js          |   7 +-
 webapp/app/js/controllers/modelSchema.js        |  86 ++-
 webapp/app/js/model/modelList.js                |   6 +-
 webapp/app/js/services/query.js                 |   2 +-
 .../cubeDesigner/advanced_settings.html         |  26 -
 .../app/partials/cubeDesigner/dimensions.html   | 560 +++++++++----------
 webapp/app/partials/cubeDesigner/info.html      | 108 ++--
 webapp/app/partials/cubeDesigner/measures.html  | 118 ++--
 webapp/app/partials/cubes/cube_schema.html      |   3 +-
 .../modelDesigner/conditions_settings.html      |  19 +-
 .../modelDesigner/model_dimensions.html         | 144 +++--
 .../partials/modelDesigner/model_measures.html  |   1 +
 webapp/app/partials/models/model_schema.html    |   4 +-
 17 files changed, 718 insertions(+), 531 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/js/controllers/cubeDimensions.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeDimensions.js b/webapp/app/js/controllers/cubeDimensions.js
index b24e9cc..f114ccb 100644
--- a/webapp/app/js/controllers/cubeDimensions.js
+++ b/webapp/app/js/controllers/cubeDimensions.js
@@ -7,7 +7,7 @@
  * "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
+ *     http://www.apache.org/license$s/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,
@@ -217,7 +217,7 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel) {
     };
 
     // Controller for cube dimension add/edit modal.
-    var cubeDimModalCtrl = function ($scope, $modalInstance, dimType) {
+    var cubeDimModalCtrl = function ($scope, $modalInstance, dimType,SweetAlert) {
         $scope.dimType = dimType;
 
         $scope.ok = function () {
@@ -227,6 +227,65 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel) {
         $scope.cancel = function () {
             $modalInstance.dismiss('cancel');
         };
+
+        $scope.checkDimension = function(){
+            var errors = [];
+            // null validate
+
+            if($scope.dimType[0]=="hierarchy"){
+                if($scope.newDimension.column.length<2){
+                    errors.push("Please define at least 2 hierarchy columns.");
+                }else{
+                    for(var i = 0;i<$scope.newDimension.column.length;i++){
+                        if($scope.newDimension.column[i]===""){
+                            errors.push("Hierarchy value can't be null.");
+                            break;
+                        }
+                    }
+                    var _columns = angular.copy($scope.newDimension.column).sort();
+                    for(var i = 0;i<_columns.length-1;i++){
+                        if(_columns[i]==_columns[i+1]&&_columns[i]!==""){
+                            errors.push("Duplicate column "+_columns[i]+".");
+                        }
+                    }
+                }
+            }
+
+            if($scope.dimType[0]=="derived"){
+                if(!$scope.newDimension.derived.length){
+                    errors.push("Please define your derived columns.");
+                }
+                for(var i = 0;i<$scope.newDimension.derived.length;i++){
+                    if($scope.newDimension.derived[i]===""){
+                        errors.push("Derived value can't be null.");
+                        break;
+                    }
+                }
+                if($scope.newDimension.derived.length>1){
+                    var _columns = angular.copy($scope.newDimension.derived).sort();
+                    for(var i = 0;i<_columns.length-1;i++){
+                        if(_columns[i]==_columns[i+1]&&_columns[i]!==""){
+                            errors.push("Duplicate column "+_columns[i]+".");
+                        }
+                    }
+                }
+
+            }
+
+            var errorInfo = "";
+            angular.forEach(errors,function(item){
+                errorInfo+="\n"+item;
+            });
+            if(errors.length){
+//                SweetAlert.swal('Warning!', errorInfo, '');
+                SweetAlert.swal('', errorInfo, 'warning');
+                return false;
+            }else{
+                return true;
+            }
+        }
+
+
     };
 
     $scope.addDim = function (dimType) {
@@ -391,8 +450,6 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel) {
         $scope.dimConflicts = conflicts;
     }, true);
 
-
-
     if ($scope.state.mode == 'edit') {
         $scope.$on('$destroy', function () {
            // $scope.dimensionsAdapter();

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/js/controllers/cubeEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeEdit.js b/webapp/app/js/controllers/cubeEdit.js
index 6b84e6a..2bbdd05 100755
--- a/webapp/app/js/controllers/cubeEdit.js
+++ b/webapp/app/js/controllers/cubeEdit.js
@@ -106,7 +106,8 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
 
     // ~ Define data
     $scope.state = {
-        "cubeSchema": ""
+        "cubeSchema": "",
+        "mode":'edit'
     };
 
     //fetch cube info and model info in edit model
@@ -115,9 +116,16 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         CubeDescService.get({cube_name: $routeParams.cubeName}, function (detail) {
             if (detail.length > 0) {
                 $scope.cubeMetaFrame = detail[0];
-                $scope.metaModel ={
-                    model : ModelList.getModel($scope.cubeMetaFrame.model_name)
+                $scope.metaModel = {};
+
+                //get model from API when page refresh
+                if(!ModelList.getModels().length){
+                    ModelDescService.get({model_name: $scope.cubeMetaFrame.model_name}, function (_model) {
+                        $scope.metaModel.model = _model;
+                    });
                 }
+                $scope.metaModel.model=ModelList.getModel($scope.cubeMetaFrame.model_name);
+
                 $scope.state.cubeSchema = angular.toJson($scope.cubeMetaFrame, true);
             }
         });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/js/controllers/cubeSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeSchema.js b/webapp/app/js/controllers/cubeSchema.js
index 37aa849..a3bbd89 100755
--- a/webapp/app/js/controllers/cubeSchema.js
+++ b/webapp/app/js/controllers/cubeSchema.js
@@ -18,22 +18,21 @@
 
 'use strict';
 
-KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserService, ProjectService, AuthenticationService,$filter,ModelService,MetaModel,CubeDescModel,CubeList,TableModel,ProjectModel,ModelDescService) {
+KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserService, ProjectService, AuthenticationService,$filter,ModelService,MetaModel,CubeDescModel,CubeList,TableModel,ProjectModel,ModelDescService,SweetAlert) {
 
     $scope.projects = [];
     $scope.newDimension = null;
     $scope.newMeasure = null;
-
-
+    $scope.forms={};
     $scope.wizardSteps = [
-        {title: 'Cube Info', src: 'partials/cubeDesigner/info.html', isComplete: false},
-        {title: 'Dimensions', src: 'partials/cubeDesigner/dimensions.html', isComplete: false},
-        {title: 'Measures', src: 'partials/cubeDesigner/measures.html', isComplete: false},
+        {title: 'Cube Info', src: 'partials/cubeDesigner/info.html', isComplete: false,form:'cube_info_form'},
+        {title: 'Dimensions', src: 'partials/cubeDesigner/dimensions.html', isComplete: false,form:'cube_dimension_form'},
+        {title: 'Measures', src: 'partials/cubeDesigner/measures.html', isComplete: false,form:'cube_measure_form'},
     ];
     if (UserService.hasRole("ROLE_ADMIN")) {
-            $scope.wizardSteps.push({title: 'Advanced Setting', src: 'partials/cubeDesigner/advanced_settings.html', isComplete: false});
+            $scope.wizardSteps.push({title: 'Advanced Setting', src: 'partials/cubeDesigner/advanced_settings.html', isComplete: false,form:'cube_setting_form'});
     }
-    $scope.wizardSteps.push({title: 'Overview', src: 'partials/cubeDesigner/overview.html', isComplete: false});
+    $scope.wizardSteps.push({title: 'Overview', src: 'partials/cubeDesigner/overview.html', isComplete: false,form:'cube_overview_form'});
 
     $scope.curStep = $scope.wizardSteps[0];
 
@@ -174,6 +173,70 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
         }
     }
 
+    $scope.checkCubeForm = function(){
+        if(!$scope.curStep.form){
+            return true;
+        }
+        if($scope.state.mode==='view'){
+            return true;
+        }
+        else{
+            //form validation
+            if($scope.forms[$scope.curStep.form].$invalid){
+                return false;
+            }else{
+                //business rule check
+                switch($scope.curStep.form){
+                    case 'cube_dimension_form':
+                        return $scope.check_cube_dimension();
+                        break;
+                    case 'cube_measure_form':
+                        return $scope.check_cube_measure();
+                        break;
+                    default:
+                        return true;
+                        break;
+                }
+            }
+        }
+    };
+
+
+    $scope.check_cube_dimension = function(){
+        var errors = [];
+        if(!$scope.cubeMetaFrame.dimensions.length){
+            errors.push("Dimension can't be null");
+        }
+        var errorInfo = "";
+        angular.forEach(errors,function(item){
+            errorInfo+="\n"+item;
+        });
+        if(errors.length){
+            SweetAlert.swal('', errorInfo, 'warning');
+            return false;
+        }else{
+            return true;
+        }
+    };
+
+    $scope.check_cube_measure = function(){
+        var errors = [];
+        if(!$scope.cubeMetaFrame.measures||!$scope.cubeMetaFrame.measures.length){
+            errors.push("Please define your metrics.");
+        }
+        var errorInfo = "";
+        angular.forEach(errors,function(item){
+            errorInfo+="\n"+item;
+        });
+        if(errors.length){
+            SweetAlert.swal('', errorInfo, 'warning');
+            return false;
+        }else{
+            return true;
+        }
+    }
+
+
     // ~ private methods
     function initProject() {
         ProjectService.list({}, function (projects) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/js/controllers/job.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/job.js b/webapp/app/js/controllers/job.js
index 0e65578..364bf92 100644
--- a/webapp/app/js/controllers/job.js
+++ b/webapp/app/js/controllers/job.js
@@ -55,10 +55,6 @@ KylinApp
               return  defer.promise;
             }
             offset = (!!offset) ? offset : 0;
-            var selectedJob = null;
-            if (angular.isDefined($scope.state.selectedJob)) {
-                selectedJob = $scope.state.selectedJob;
-            }
 
             var statusIds = [];
             angular.forEach($scope.status, function (statusObj, index) {
@@ -77,6 +73,9 @@ KylinApp
             var defer = $q.defer();
             return JobList.list(jobRequest).then(function(resp){
                 $scope.state.loading = false;
+                if (angular.isDefined($scope.state.selectedJob)) {
+                    $scope.state.selectedJob = JobList.jobs[ $scope.state.selectedJob.uuid];
+                }
                 defer.resolve(resp);
                 return defer.promise;
             });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/js/controllers/modelEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelEdit.js b/webapp/app/js/controllers/modelEdit.js
index 30f4c21..8e676d2 100644
--- a/webapp/app/js/controllers/modelEdit.js
+++ b/webapp/app/js/controllers/modelEdit.js
@@ -23,6 +23,7 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
     //add or edit ?
     var absUrl = $location.absUrl();
     $scope.modelMode = absUrl.indexOf("/models/add")!=-1?'addNewModel':absUrl.indexOf("/models/edit")!=-1?'editExistModel':'default';
+    $scope.cubeConfig = cubeConfig;
 
 
     $scope.getPartitonColumns = function(tableName){
@@ -123,7 +124,7 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
         return $interpolate($templateCache.get(tmpl))(notification);
     };
 
-    $scope.saveModel = function (design_form) {
+    $scope.saveModel = function () {
 
         try {
             angular.fromJson($scope.state.modelSchema);
@@ -149,10 +150,6 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
                         if (request.successful) {
                             $scope.state.modelSchema = request.modelSchema;
                             MessageService.sendMsg($scope.modelResultTmpl({'text':'Updated the model successfully.',type:'success'}), 'success', {}, true, 'top_center');
-
-                            if (design_form) {
-                                design_form.$invalid = true;
-                            }
                         } else {
                             $scope.saveModelRollBack();
                                 var message =request.message;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/js/controllers/modelSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelSchema.js b/webapp/app/js/controllers/modelSchema.js
index 883bb3a..2ec1fa7 100644
--- a/webapp/app/js/controllers/modelSchema.js
+++ b/webapp/app/js/controllers/modelSchema.js
@@ -32,9 +32,9 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
     $scope.wizardSteps = [
         {title: 'Model Info', src: 'partials/modelDesigner/model_info.html', isComplete: false,form:'model_info_form'},
         {title: 'Data Model', src: 'partials/modelDesigner/data_model.html', isComplete: false,form:'data_model_form'},
-        {title: 'Dimensions', src: 'partials/modelDesigner/model_dimensions.html', isComplete: false,form:'model_dimensions'},
-        {title: 'Measures', src: 'partials/modelDesigner/model_measures.html', isComplete: false,form:null},
-        {title: 'Settings', src: 'partials/modelDesigner/conditions_settings.html', isComplete: false,form:null}
+        {title: 'Dimensions', src: 'partials/modelDesigner/model_dimensions.html', isComplete: false,form:'model_dimensions_form'},
+        {title: 'Measures', src: 'partials/modelDesigner/model_measures.html', isComplete: false,form:'model_measure_form'},
+        {title: 'Settings', src: 'partials/modelDesigner/conditions_settings.html', isComplete: false,form:'model_setting_form'}
     ];
 
     $scope.curStep = $scope.wizardSteps[0];
@@ -111,7 +111,16 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
                 switch($scope.curStep.form){
                     case 'data_model_form':
                         return $scope.check_data_model();
-                     break;
+                         break;
+                    case 'model_dimensions_form':
+                        return $scope.check_model_dimensions();
+                         break;
+                    case 'model_measure_form':
+                        return $scope.check_model_measure();
+                         break;
+                    case 'model_setting_form':
+                        return $scope.check_model_setting();
+                         break;
                     default:
                         return true;
                         break;
@@ -141,6 +150,75 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
 
     }
 
+    /*
+    * dimensions validation
+    * 1.dimension can't be null
+    */
+    $scope.check_model_dimensions = function(){
+
+        var errors = [];
+        if(!$scope.model.dimensions.length){
+            errors.push("No dimensions defined.");
+        }
+        angular.forEach($scope.model.dimensions,function(_dimension){
+            if(!_dimension.columns||!_dimension.columns.length){
+            errors.push("No dimension columns defined for Table["+_dimension.table+"]");
+            }
+        });
+        var errorInfo = "";
+        angular.forEach(errors,function(item){
+            errorInfo+="\n"+item;
+        });
+        if(errors.length){
+            SweetAlert.swal('', errorInfo, 'warning');
+            return false;
+        }else{
+            return true;
+        }
+
+    };
+
+    /*
+     * dimensions validation
+     * 1.metric can't be null
+     */
+    $scope.check_model_measure = function(){
+
+        var errors = [];
+        if(!$scope.model.metrics||!$scope.model.metrics.length){
+            errors.push("Please define your metrics.");
+        }
+        var errorInfo = "";
+        angular.forEach(errors,function(item){
+            errorInfo+="\n"+item;
+        });
+        if(errors.length){
+            SweetAlert.swal('', errorInfo, 'warning');
+            return false;
+        }else{
+            return true;
+        }
+
+    };
+    $scope.check_model_setting = function(){
+        var errors = [];
+        if($scope.model.partition_desc.partition_date_column!=null&& $scope.model.partition_desc.partition_date_start==null){
+            errors.push("Please indicate start date when partition date column selected.");
+        }
+        if($scope.model.partition_desc.partition_date_column==null&& $scope.model.partition_desc.partition_date_start!=null){
+            errors.push("Please select your partitoin date column.");
+        }
+        var errorInfo = "";
+        angular.forEach(errors,function(item){
+            errorInfo+="\n"+item;
+        });
+        if(errors.length){
+            SweetAlert.swal('', errorInfo, 'warning');
+            return false;
+        }else{
+            return true;
+        }
+    }
 
 
     $scope.goToStep = function(stepIndex){

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/js/model/modelList.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/modelList.js b/webapp/app/js/model/modelList.js
index b7dba7b..388cabc 100644
--- a/webapp/app/js/model/modelList.js
+++ b/webapp/app/js/model/modelList.js
@@ -17,8 +17,8 @@
 */
 
 KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService,ProjectModel,$log){
-    var models=[];
     var _this = this;
+    this.models=[];
 
     this.list = function(queryParam){
 
@@ -72,6 +72,10 @@ KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService,
         })
     }
 
+    this.getModels = function(){
+        return _this.models;
+    }
+
     this.getModelByCube = function(cubeName){
         return  _.find(_this.models,function(model){
             return _.some(model.cubes,function(_cube){

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/js/services/query.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/services/query.js b/webapp/app/js/services/query.js
index cb82a54..6434a7e 100644
--- a/webapp/app/js/services/query.js
+++ b/webapp/app/js/services/query.js
@@ -18,7 +18,7 @@
 
 KylinApp.factory('QueryService', ['$resource', function ($resource, config) {
     return $resource(Config.service.url + ':subject/:subject_id/:propName/:propValue/:action', {}, {
-        query: {method: 'POST', params: {action: 'query'}, isArray: false},
+        query: {method: 'POST', params: {action: 'query'},timeout:300000, isArray: false},
         save: {method: 'POST', params: {subject: 'saved_queries'}, isArray: false},
         delete: {method: 'DELETE', params: {subject: 'saved_queries'}, isArray: false},
         list: {method: 'GET', params: {subject: 'saved_queries'}, isArray: true},

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/partials/cubeDesigner/advanced_settings.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/advanced_settings.html b/webapp/app/partials/cubeDesigner/advanced_settings.html
index 164ca05..cb2eaed 100755
--- a/webapp/app/partials/cubeDesigner/advanced_settings.html
+++ b/webapp/app/partials/cubeDesigner/advanced_settings.html
@@ -18,32 +18,6 @@
 
 <div ng-controller="CubeAdvanceSettingCtrl">
 <div>
-
-    <div class="form-group">
-
-        <table style="margin-left:42px; width:92%"
-               class="table table-hover list">
-            <tr>
-                <td>
-                    <!--Cube Size-->
-                    <div class="form-group" ng-show="userService.hasRole('ROLE_ADMIN')">
-                        <div class="row">
-                            <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Cube Size</b></label>
-                            <div class="col-xs-12 col-sm-6">
-                                <select class="form-control" ng-if="state.mode=='edit'" style="width: 360px;"
-                                        chosen ng-model="metaModel.model.capacity" required
-                                        ng-options="cc as cc for cc in cubeConfig.cubeCapacities">
-                                    <option value=""></option>
-                                </select>
-                                <span ng-if="state.mode=='view'">{{metaModel.model.capacity}}</span>
-                            </div>
-                        </div>
-                    </div>
-                </td>
-            </tr>
-        </table>
-
-    </div>
     <div class="form-group">
         <h4 style="margin-left:42px">Aggregation Groups</h4>
         <table style="margin-left:42px; width:92%"

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/partials/cubeDesigner/dimensions.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/dimensions.html b/webapp/app/partials/cubeDesigner/dimensions.html
index 5a025f4..94ce1fd 100644
--- a/webapp/app/partials/cubeDesigner/dimensions.html
+++ b/webapp/app/partials/cubeDesigner/dimensions.html
@@ -17,338 +17,338 @@
 -->
 
 <div ng-controller="CubeDimensionsCtrl">
-
+<ng-form name="forms.cube_dimension_form" novalidate>
 <!-- Dimensions Summary -->
-<div class="dataTables_wrapper form-inline no-footer">
-    <div class="row">
-        <div class="col-xs-6" ng-if="state.mode=='edit'">
-            <div class="btn-group">
-                <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
-                    <i class="fa fa-plus"></i> Add Dimension <span class="ace-icon fa fa-caret-down icon-on-right"></span>
+    <div class="dataTables_wrapper form-inline no-footer">
+        <div class="row">
+            <div class="col-xs-6" ng-if="state.mode=='edit'">
+                <div class="btn-group">
+                    <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
+                        <i class="fa fa-plus"></i> Add Dimension <span class="ace-icon fa fa-caret-down icon-on-right"></span>
+                    </button>
+                    <ul class="dropdown-menu" role="menu">
+                        <li><a ng-click="addDim('normal')">Normal</a></li>
+                        <li><a ng-click="addDim('hierarchy')">Hierarchy</a></li>
+                        <li><a ng-click="addDim('derived')">Derived</a></li>
+                    </ul>
+                </div>
+                <button type="button" class="btn btn-default" ng-disabled="!metaModel.model.fact_table.length"
+                        ng-click="openAutoGenModal()">
+                    <i class="fa fa-building-o"></i> Auto Generator
                 </button>
-                <ul class="dropdown-menu" role="menu">
-                    <li><a ng-click="addDim('normal')">Normal</a></li>
-                    <li><a ng-click="addDim('hierarchy')">Hierarchy</a></li>
-                    <li><a ng-click="addDim('derived')">Derived</a></li>
-                </ul>
             </div>
-            <button type="button" class="btn btn-default" ng-disabled="!metaModel.model.fact_table.length"
-                    ng-click="openAutoGenModal()">
-                <i class="fa fa-building-o"></i> Auto Generator
-            </button>
-        </div>
-        <div class="col-xs-6" ng-if="state.mode!='edit'">
-        </div>
-        <div class="col-xs-6">
-            <b>Dimensions</b>
-            <span class="pull-right input-icon input-icon-right nav-search" style="margin-left: 22px;">
-                <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="dimState.filter"/>
-                <i class="ace-icon fa fa-search nav-search-icon"></i>
-            </span>
+            <div class="col-xs-6" ng-if="state.mode!='edit'">
+            </div>
+            <div class="col-xs-6">
+                <b>Dimensions</b>
+                <span class="pull-right input-icon input-icon-right nav-search" style="margin-left: 22px;">
+                    <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="dimState.filter"/>
+                    <i class="ace-icon fa fa-search nav-search-icon"></i>
+                </span>
+            </div>
         </div>
-    </div>
-    <table class="table table-striped table-hover" ng-if="cubeMetaFrame.dimensions.length > 0">
-        <thead>
-            <tr>
-                <th>ID</th>
-                <th>Name</th>
-                <th>Table Name</th>
-                <th>Type</th>
-                <th></th>
-                <th ng-if="state.mode=='edit'">Actions</th>
-            </tr>
-        </thead>
-        <tbody class="cube-dimension">
-            <tr ng-repeat="dimension in cubeMetaFrame.dimensions | filter:dimState.filter track by $index">
-                <!--ID -->
-                <td>
-                    <b>{{dimension.id = ($index + 1)}}</b>
-                </td>
-                <!--Name -->
-                <td>
-                    <span>{{dimension.name}}</span>
-                </td>
-                <!--Table Name -->
-                <td>
-                    <span tooltip="{{dimension.table == metaModel.model.fact_table ? 'Fact Table' : 'Lookup Table'}}">{{dimension.table}}</span>
-                </td>
-                <!--Type-->
-                <td>
-                    <span class="label label-primary" ng-repeat="t in getDimType(dimension)">{{t}}</span>
-                </td>
-                <!--Columns-->
-                <td>
-                    <div ng-repeat="t in getDimType(dimension)">
-                        <div ng-switch="t">
-                            <dl class="dl-horizontal" ng-switch-when="hierarchy">
-                                <dt>Hierarchy</dt>
-                                <dd>{{dimension.column}}</dd>
-                            </dl>
-                            <dl class="dl-horizontal" ng-switch-when="derived">
-                                <dt>Derived</dt>
-                                <dd>{{dimension.derived}}</dd>
-                            </dl>
-                            <dl class="dl-horizontal" ng-switch-when="normal">
-                                <dt>Column</dt>
-                                <dd>{{dimension.column}}</dd>
-                            </dl>
+        <table class="table table-striped table-hover" ng-if="cubeMetaFrame.dimensions.length > 0">
+            <thead>
+                <tr>
+                    <th>ID</th>
+                    <th>Name</th>
+                    <th>Table Name</th>
+                    <th>Type</th>
+                    <th></th>
+                    <th ng-if="state.mode=='edit'">Actions</th>
+                </tr>
+            </thead>
+            <tbody class="cube-dimension">
+                <tr ng-repeat="dimension in cubeMetaFrame.dimensions | filter:dimState.filter track by $index">
+                    <!--ID -->
+                    <td>
+                        <b>{{dimension.id = ($index + 1)}}</b>
+                    </td>
+                    <!--Name -->
+                    <td>
+                        <span>{{dimension.name}}</span>
+                    </td>
+                    <!--Table Name -->
+                    <td>
+                        <span tooltip="{{dimension.table == metaModel.model.fact_table ? 'Fact Table' : 'Lookup Table'}}">{{dimension.table}}</span>
+                    </td>
+                    <!--Type-->
+                    <td>
+                        <span class="label label-primary" ng-repeat="t in getDimType(dimension)">{{t}}</span>
+                    </td>
+                    <!--Columns-->
+                    <td>
+                        <div ng-repeat="t in getDimType(dimension)">
+                            <div ng-switch="t">
+                                <dl class="dl-horizontal" ng-switch-when="hierarchy">
+                                    <dt>Hierarchy</dt>
+                                    <dd>{{dimension.column}}</dd>
+                                </dl>
+                                <dl class="dl-horizontal" ng-switch-when="derived">
+                                    <dt>Derived</dt>
+                                    <dd>{{dimension.derived}}</dd>
+                                </dl>
+                                <dl class="dl-horizontal" ng-switch-when="normal">
+                                    <dt>Column</dt>
+                                    <dd>{{dimension.column}}</dd>
+                                </dl>
+                            </div>
                         </div>
-                    </div>
-                </td>
-                <td ng-if="state.mode=='edit'">
-                    <!--edit button-->
-                    <button class="btn btn-xs btn-info"
-                            ng-click="editDim(dimension)"><i class="fa fa-pencil"></i>
-                    </button>
-                    <!-- remove button-->
-                    <button class="btn btn-xs btn-danger"
-                            ng-click="removeDim(dimension)"><i class="fa fa-trash-o"></i>
-                    </button>
-                </td>
-            </tr>
-        </tbody>
-    </table>
-</div>
+                    </td>
+                    <td ng-if="state.mode=='edit'">
+                        <!--edit button-->
+                        <button class="btn btn-xs btn-info"
+                                ng-click="editDim(dimension)"><i class="fa fa-pencil"></i>
+                        </button>
+                        <!-- remove button-->
+                        <button class="btn btn-xs btn-danger"
+                                ng-click="removeDim(dimension)"><i class="fa fa-trash-o"></i>
+                        </button>
+                    </td>
+                </tr>
+            </tbody>
+        </table>
+    </div>
 
-<div class="space-16"></div>
-<div class="callout callout-warning dimensions-conflict-area" ng-if="dimConflicts.length">
-    <h4>There are following columns defined in multiple dimensions. <small>This is not recommended!</small></h4>
-    <div class="row" ng-repeat="c in dimConflicts">
-        <div class="col-xs-3">
-            <code>{{c.table}}.{{c.column}}</code>
-        </div>
-        <div class="col-xs-3">
-            <ul class="list-unstyled">
-                <li ng-repeat="d in c.dims">{{d.id}} - {{d.name}}</li>
-            </ul>
+    <div class="space-16"></div>
+    <div class="callout callout-warning dimensions-conflict-area" ng-if="dimConflicts.length">
+        <h4>There are following columns defined in multiple dimensions. <small>This is not recommended!</small></h4>
+        <div class="row" ng-repeat="c in dimConflicts">
+            <div class="col-xs-3">
+                <code>{{c.table}}.{{c.column}}</code>
+            </div>
+            <div class="col-xs-3">
+                <ul class="list-unstyled">
+                    <li ng-repeat="d in c.dims">{{d.id}} - {{d.name}}</li>
+                </ul>
+            </div>
         </div>
     </div>
-</div>
 
-<!-- Edit Dimension Form -->
-<script type="text/ng-template" id="addEditDimension.html">
-    <div class="modal-header">
-        <h4 class="box-title lighter">{{dimState.editing ? 'Edit' : 'Add'}} Dimension
-            <span class="label label-primary" ng-repeat="t in dimType">{{t}}</span>
-        </h4>
-    </div>
-    <div class="modal-body">
-        <ng-form name="edit_dim_form">
-        <div class="row">
-            <div class="col-xs-8">
-                <!--Name-->
-                <div class="form-group">
-                    <div class="row">
-                        <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Name</b></label>
-                        <div class="col-xs-12 col-sm-6">
-                            <input type="text" placeholder="Name.." class="form-control" name="dim_name"
-                                   tooltip="dimension name.." tooltip-trigger="focus"
-                                   ng-model="newDimension.name" required />
-                        </div>
-                        <div class="col-xs-12 col-sm-3">
-                            <div class="text-warning" ng-if="edit_dim_form.dim_name.$error.required  && edit_dim_form.dim_name.$dirty">
-                                The Dimension Name is required.
+    <!-- Edit Dimension Form -->
+    <script type="text/ng-template" id="addEditDimension.html">
+        <div class="modal-header">
+            <h4 class="box-title lighter">{{dimState.editing ? 'Edit' : 'Add'}} Dimension
+                <span class="label label-primary" ng-repeat="t in dimType">{{t}}</span>
+            </h4>
+        </div>
+        <div class="modal-body">
+            <ng-form name="edit_dim_form">
+            <div class="row">
+                <div class="col-xs-8">
+                    <!--Name-->
+                    <div class="form-group">
+                        <div class="row">
+                            <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Name</b></label>
+                            <div class="col-xs-12 col-sm-6">
+                                <input type="text" placeholder="Name.." class="form-control" name="dim_name"
+                                       tooltip="dimension name.." tooltip-trigger="focus"
+                                       ng-model="newDimension.name" required />
+                            </div>
+                            <div class="col-xs-12 col-sm-3">
+                                <div class="text-warning" ng-if="edit_dim_form.dim_name.$error.required  && edit_dim_form.dim_name.$dirty">
+                                    The Dimension Name is required.
+                                </div>
                             </div>
                         </div>
                     </div>
-                </div>
 
-                <!--Table Name: derived dimension only allows lookup tables-->
-                <div class="form-group">
-                    <div class="row">
-                        <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Table Name</b></label>
-                        <div class="col-xs-12 col-sm-6" ng-if="dimType.indexOf('derived') >= 0">
-                            <select class="form-control" required="true" chosen data-placeholder="Select a lookup table"
-                                    ng-model="newDimension.table" ng-options="table for table in availableTables.slice(1)">
-                                <option value=""></option>
-                            </select>
-                        </div>
-                        <div class="col-xs-12 col-sm-6" ng-if="dimType.indexOf('derived') == -1">
-                            <select class="form-control" required="true" chosen data-placeholder="Select a table"
-                                    ng-model="newDimension.table" ng-options="table for table in availableTables">
-                                <option value=""></option>
-                            </select>
-                        </div>
-                        <div class="col-xs-12 col-sm-3">
-                            <div class="text-info" ng-if="dimType.indexOf('derived') >= 0">
-                                Derived dimension only comes from lookup table.
+                    <!--Table Name: derived dimension only allows lookup tables-->
+                    <div class="form-group">
+                        <div class="row">
+                            <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Table Name</b></label>
+                            <div class="col-xs-12 col-sm-6" ng-if="dimType.indexOf('derived') >= 0">
+                                <select class="form-control" required="true" chosen data-placeholder="Select a lookup table"
+                                        ng-model="newDimension.table" ng-options="table for table in availableTables.slice(1)">
+                                    <option value=""></option>
+                                </select>
+                            </div>
+                            <div class="col-xs-12 col-sm-6" ng-if="dimType.indexOf('derived') == -1">
+                                <select class="form-control" required="true" chosen data-placeholder="Select a table"
+                                        ng-model="newDimension.table" ng-options="table for table in availableTables">
+                                    <option value=""></option>
+                                </select>
+                            </div>
+                            <div class="col-xs-12 col-sm-3">
+                                <div class="text-info" ng-if="dimType.indexOf('derived') >= 0">
+                                    Derived dimension only comes from lookup table.
+                                </div>
                             </div>
                         </div>
                     </div>
-                </div>
 
-                <!--Normal Dimension: choose one column-->
-                <div class="form-group" ng-if="dimType.indexOf('normal') >= 0">
-                    <div class="row">
-                        <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Column Name</b></label>
-                        <div class="col-xs-12 col-sm-6">
-                            <select class="form-control" required="true" chosen data-placeholder="Select a column"
-                                    ng-model="newDimension.column[0]" ng-options="column.name as column.name for column in getDimColumnsByTable(newDimension.table)">
-                                <option value=""></option>
-                            </select>
+                    <!--Normal Dimension: choose one column-->
+                    <div class="form-group" ng-if="dimType.indexOf('normal') >= 0">
+                        <div class="row">
+                            <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Column Name</b></label>
+                            <div class="col-xs-12 col-sm-6">
+                                <select class="form-control" required="true" chosen data-placeholder="Select a column"
+                                        ng-model="newDimension.column[0]" ng-options="column.name as column.name for column in getDimColumnsByTable(newDimension.table)">
+                                    <option value=""></option>
+                                </select>
+                            </div>
                         </div>
                     </div>
-                </div>
 
-                <!--Hierarchy Dimension-->
-                <div class="form-group" ng-if="dimType.indexOf('hierarchy') >= 0">
-                    <div class="row">
-                        <div class="col-sm-6 col-sm-offset-3">
-                            <div ui-sortable="{containment: 'parent', placeholder: 'hierarchy-item-placeholder', forcePlaceholderSize: true, opacity: 0.8}"
-                                 ng-model="newDimension.column" class="hierarchy-container">
-                                <div ng-repeat="hierarchyIndex in [] | range: newDimension.column.length" class="hierarchy-item">
-                                    <div class="row">
-                                        <div class="col-xs-2">
-                                            <span class="badge">{{$index + 1}}</span>
-                                        </div>
-                                        <div class="col-xs-8">
-                                            <select chosen style="width: 100%"
-                                                    data-placeholder="Dimension Hierarchy Column"
-                                                    ng-model="newDimension.column[$index]"
-                                                    ng-options="columns.name as columns.name for columns in getDimColumnsByTable(newDimension.table)" >
-                                                <option value="">-- Select Column --</option>
-                                            </select>
-                                        </div>
-                                        <div class="col-xs-2">
-                                            <button type="button" class="pull-right btn btn-xs btn-danger" style="cursor: pointer " tooltip="Delete"
-                                                    ng-click="newDimension.column.splice($index, 1);">
-                                                <i class="fa fa-trash-o"></i>
-                                            </button>
+                    <!--Hierarchy Dimension-->
+                    <div class="form-group" ng-if="dimType.indexOf('hierarchy') >= 0">
+                        <div class="row">
+                            <div class="col-sm-6 col-sm-offset-3">
+                                <div ui-sortable="{containment: 'parent', placeholder: 'hierarchy-item-placeholder', forcePlaceholderSize: true, opacity: 0.8}"
+                                     ng-model="newDimension.column" class="hierarchy-container">
+                                    <div ng-repeat="hierarchyIndex in [] | range: newDimension.column.length" class="hierarchy-item">
+                                        <div class="row">
+                                            <div class="col-xs-2">
+                                                <span class="badge">{{$index + 1}}</span>
+                                            </div>
+                                            <div class="col-xs-8">
+                                                <select chosen style="width: 100%"
+                                                        data-placeholder="Dimension Hierarchy Column"
+                                                        ng-model="newDimension.column[$index]"
+                                                        ng-options="columns.name as columns.name for columns in getDimColumnsByTable(newDimension.table)" >
+                                                    <option value="">-- Select Column --</option>
+                                                </select>
+                                            </div>
+                                            <div class="col-xs-2">
+                                                <button type="button" class="pull-right btn btn-xs btn-danger" style="cursor: pointer " tooltip="Delete"
+                                                        ng-click="newDimension.column.splice($index, 1);">
+                                                    <i class="fa fa-trash-o"></i>
+                                                </button>
+                                            </div>
                                         </div>
                                     </div>
                                 </div>
-                            </div>
 
-                            <div class="space-8"></div>
+                                <div class="space-8"></div>
 
-                            <div class="row">
-                                <div class="col-xs-4">
-                                    <button class="btn btn-xs btn-info"
-                                            ng-click="newDimension.column.push('');">
-                                        <i class="fa fa-plus"></i> New Hierarchy</button>
-                                </div>
-                                <div class="col-xs-8">
-                                    <p class="help-block">Drag level into the order you prefer.</p>
+                                <div class="row">
+                                    <div class="col-xs-4">
+                                        <button class="btn btn-xs btn-info"
+                                                ng-click="newDimension.column.push('');">
+                                            <i class="fa fa-plus"></i> New Hierarchy</button>
+                                    </div>
+                                    <div class="col-xs-8">
+                                        <p class="help-block">Drag level into the order you prefer.</p>
+                                    </div>
                                 </div>
                             </div>
                         </div>
                     </div>
-                </div>
 
-                <!--Derived Dimension-->
-                <div ng-if="dimType.indexOf('derived') >= 0">
-                    <div class="form-group">
-                        <div class="row">
-                            <div class="col-sm-6 col-sm-offset-3">
-                                <div ng-repeat="derived in newDimension.derived track by $index">
-                                    <div>
-                                        <select chosen style="width: 80%;" data-placeholder="Derived Columns.."
-                                                ng-model="newDimension.derived[$index]"
-                                                ng-options="columns.name as columns.name for columns in getDimColumnsByTable(newDimension.table)" >
-                                            <option value=""></option>
-                                        </select>
-                                        <button class="pull-right btn btn-xs btn-danger" style="cursor: pointer " tooltip="Delete"
-                                                ng-click="newDimension.derived.splice($index, 1);">
-                                            <i class="fa fa-trash-o"></i>
-                                        </button>
-                                        <div class="space-4"></div>
+                    <!--Derived Dimension-->
+                    <div ng-if="dimType.indexOf('derived') >= 0">
+                        <div class="form-group">
+                            <div class="row">
+                                <div class="col-sm-6 col-sm-offset-3">
+                                    <div ng-repeat="derived in newDimension.derived track by $index">
+                                        <div>
+                                            <select chosen style="width: 80%;" data-placeholder="Derived Columns.."
+                                                    ng-model="newDimension.derived[$index]"
+                                                    ng-options="columns.name as columns.name for columns in getDimColumnsByTable(newDimension.table)" >
+                                                <option value=""></option>
+                                            </select>
+                                            <button class="pull-right btn btn-xs btn-danger" style="cursor: pointer " tooltip="Delete"
+                                                    ng-click="newDimension.derived.splice($index, 1);">
+                                                <i class="fa fa-trash-o"></i>
+                                            </button>
+                                            <div class="space-4"></div>
+                                        </div>
                                     </div>
+                                    <button class="btn btn-xs btn-info" ng-click="newDimension.derived.push('');">
+                                        <i class="fa fa-plus"></i> New Derived</button>
                                 </div>
-                                <button class="btn btn-xs btn-info" ng-click="newDimension.derived.push('');">
-                                    <i class="fa fa-plus"></i> New Derived</button>
                             </div>
                         </div>
                     </div>
                 </div>
-            </div>
 
-            <!--Tips-->
-            <div class="col-xs-4">
-                <div class="box box-solid">
-                    <div class="box-header">
-                        <h4 class="box-title">Tips</h4>
-                    </div>
-                    <div class="box-body">
-                        <div class="row">
-                            <div class="col-xs-12">
-                                <ol class="text-info">
-                                    <li>Type in any input box for auto suggestion</li>
-                                    <li>Pick up Fact Table from Star Schema Tables first</li>
-                                    <li>Data Type should match with Hive Table's Data Type</li>
-                                    <li>Join Type have to be same as will be used in query</li>
-                                    <li>Using Hierarchy to inherit one dimension another</li>
-                                    <li>Using Derived for One-One relationship between columns, like ID and Name</li>
-                                </ol>
+                <!--Tips-->
+                <div class="col-xs-4">
+                    <div class="box box-solid">
+                        <div class="box-header">
+                            <h4 class="box-title">Tips</h4>
+                        </div>
+                        <div class="box-body">
+                            <div class="row">
+                                <div class="col-xs-12">
+                                    <ol class="text-info">
+                                        <li>Type in any input box for auto suggestion</li>
+                                        <li>Pick up Fact Table from Star Schema Tables first</li>
+                                        <li>Data Type should match with Hive Table's Data Type</li>
+                                        <li>Join Type have to be same as will be used in query</li>
+                                        <li>Using Hierarchy to inherit one dimension another</li>
+                                        <li>Using Derived for One-One relationship between columns, like ID and Name</li>
+                                    </ol>
+                                </div>
                             </div>
                         </div>
                     </div>
                 </div>
             </div>
+            </ng-form>
         </div>
-        </ng-form>
-    </div>
-    <div class="modal-footer">
-        <button class="btn btn-primary" ng-disabled="edit_dim_form.$invalid" ng-click="ok()">OK</button>
-        <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
-    </div>
-</script>
+        <div class="modal-footer">
+            <button class="btn btn-primary" ng-disabled="edit_dim_form.$invalid" ng-click="checkDimension()?ok():''">OK</button>
+            <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
+        </div>
+    </script>
 
 
-<script type="text/ng-template" id="autoGenDimension.html">
-    <div class="modal-header">
-        <h4 class="box-title lighter">Auto Generate Dimensions <small>This is a helper for you to batch generate dimensions.</small></h4>
-    </div>
-    <div class="modal-body">
-        <div class="row">
-            <div class="col-xs-8">
-                <div class="box box-solid">
-                    <div class="box-header"><h4>Columns</h4></div>
-                    <div class="box-body">
-                        <ul class="list-unstyled columns-region">
-                            <li ng-repeat="table in availableTables track by $index">
-                                <h5 class="table-name-underline">
-                                    <b>{{table}}</b>{{$index == 0 ? ' [Fact Table]' : ' [Lookup Table]'}}
-                                </h5>
-                                <ul class="list-unstyled">
-                                    <li ng-repeat="col in availableColumns[table] track by col.table + '.' + col.name">
-                                        <label>
-                                            <input type="checkbox" ng-model="selectedColumns[table][col.name].selected"
-                                                   ng-disabled="selectedColumns[table][col.name].disabled">
-                                            {{col.name}}
-                                        </label>
-                                    </li>
-                                </ul>
-                            </li>
-                        </ul>
+    <script type="text/ng-template" id="autoGenDimension.html">
+        <div class="modal-header">
+            <h4 class="box-title lighter">Auto Generate Dimensions <small>This is a helper for you to batch generate dimensions.</small></h4>
+        </div>
+        <div class="modal-body">
+            <div class="row">
+                <div class="col-xs-8">
+                    <div class="box box-solid">
+                        <div class="box-header"><h4>Columns</h4></div>
+                        <div class="box-body">
+                            <ul class="list-unstyled columns-region">
+                                <li ng-repeat="table in availableTables track by $index">
+                                    <h5 class="table-name-underline">
+                                        <b>{{table}}</b>{{$index == 0 ? ' [Fact Table]' : ' [Lookup Table]'}}
+                                    </h5>
+                                    <ul class="list-unstyled">
+                                        <li ng-repeat="col in availableColumns[table] track by col.table + '.' + col.name">
+                                            <label>
+                                                <input type="checkbox" ng-model="selectedColumns[table][col.name].selected"
+                                                       ng-disabled="selectedColumns[table][col.name].disabled">
+                                                {{col.name}}
+                                            </label>
+                                        </li>
+                                    </ul>
+                                </li>
+                            </ul>
+                        </div>
                     </div>
                 </div>
-            </div>
 
-            <!--Tips-->
-            <div class="col-xs-4">
-                <div class="box box-solid">
-                    <div class="box-header">
-                        <h4 class="box-title">Auto Generate Rules</h4>
-                    </div>
-                    <div class="box-body">
-                        <div class="row">
-                            <div class="col-xs-12">
-                                <ol class="text-info">
-                                    <li>Column is disabled once there is already a dimension referred this column.</li>
-                                    <li>In fact table: one normal dimension will be auto generated per column.</li>
-                                    <li>In lookup table: one derived dimension will be auto generated for all the selected columns.</li>
-                                </ol>
+                <!--Tips-->
+                <div class="col-xs-4">
+                    <div class="box box-solid">
+                        <div class="box-header">
+                            <h4 class="box-title">Auto Generate Rules</h4>
+                        </div>
+                        <div class="box-body">
+                            <div class="row">
+                                <div class="col-xs-12">
+                                    <ol class="text-info">
+                                        <li>Column is disabled once there is already a dimension referred this column.</li>
+                                        <li>In fact table: one normal dimension will be auto generated per column.</li>
+                                        <li>In lookup table: one derived dimension will be auto generated for all the selected columns.</li>
+                                    </ol>
+                                </div>
                             </div>
                         </div>
                     </div>
                 </div>
             </div>
         </div>
-    </div>
-    <div class="modal-footer">
-        <button class="btn btn-primary" ng-disabled="" ng-click="ok()">OK</button>
-        <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
-    </div>
-</script>
-
+        <div class="modal-footer">
+            <button class="btn btn-primary" ng-disabled="" ng-click="ok()">OK</button>
+            <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
+        </div>
+    </script>
+    </ng-form>
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/partials/cubeDesigner/info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/info.html b/webapp/app/partials/cubeDesigner/info.html
index bd6aed2..d724ffd 100644
--- a/webapp/app/partials/cubeDesigner/info.html
+++ b/webapp/app/partials/cubeDesigner/info.html
@@ -18,73 +18,71 @@
 
 <div class="row">
     <div class="col-xs-8">
-        <!--Project-->
-        <div class="form-group">
-            <div class="row">
-                <label class="col-xs-12 col-sm-3 control-label no-padding-right">
-                    <b>Model Name</b>
-                </label>
-                <div class="col-xs-12 col-sm-6">
-                    <input ng-if="state.mode=='edit'" name="project_name" type="text" class="form-control"
-                           ng-model="cubeMetaFrame.model_name"/>
-                    <span ng-if="state.mode=='view'">
-                        {{cubeMetaFrame.model_name}}
-                    </span>
+        <ng-form name="forms.cube_info_form" novalidate>
+            <!--Project-->
+            <div class="form-group">
+                <div class="row">
+                    <label class="col-xs-12 col-sm-3 control-label no-padding-right">
+                        <b>Model Name</b>
+                    </label>
+                    <div class="col-xs-12 col-sm-6"  ng-class="forms.cube_info_form.model_name.$invalid?'has-error':''">
+                        <input ng-if="state.mode=='edit'" name="model_name" type="text" required class="form-control"
+                               ng-model="cubeMetaFrame.model_name"/>
+                        <small class="help-block" ng-show="forms.cube_info_form.model_name.$error.required">The model is required</small>
+                        <span ng-if="state.mode=='view'">
+                            {{cubeMetaFrame.model_name}}
+                        </span>
+                    </div>
                 </div>
             </div>
-        </div>
 
-        <!--Cube Name-->
-        <div class="form-group">
-            <div class="row">
-                <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
-                    <b>Cube Name</b>
-                </label>
-                <div class="col-xs-12 col-sm-6">
-                    <input ng-if="state.mode=='edit'" name="cube_name" type="text" class="form-control"
-                           ng-model="cubeMetaFrame.name" required
-                           placeholder="You can use letters, numbers, and '_'"
-                           ng-maxlength=100 ng-pattern="/^\w+$/" />
-                    <span ng-if="state.mode=='view'">{{cubeMetaFrame.name}}</span>
-                </div>
-                <div class="col-xs-12 col-sm-3">
-                    <div class="text-warning" ng-if="design_form.cube_name.$error.required  && design_form.cube_name.$dirty">
-                        Cube name is required.
-                    </div>
-                    <div class="text-warning" ng-if="design_form.cube_name.$invalid && design_form.cube_name.$dirty && !design_form.cube_name.$error.required">
-                        Cube name is invalid.
+            <!--Cube Name-->
+            <div class="form-group">
+                <div class="row">
+                    <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
+                        <b>Cube Name</b>
+                    </label>
+                    <div class="col-xs-12 col-sm-6" ng-class="forms.cube_info_form.cube_name.$invalid?'has-error':''">
+                        <input ng-if="state.mode=='edit'" name="cube_name" type="text" class="form-control"
+                               ng-model="cubeMetaFrame.name" required
+                               placeholder="You can use letters, numbers, and '_'"
+                               ng-maxlength=100 ng-pattern="/^\w+$/" />
+                        <small class="help-block" ng-show="forms.cube_info_form.cube_name.$error.required  && forms.cube_info_form.cube_name.$dirty">Cube name is required.</small>
+                        <small class="help-block" ng-show="forms.cube_info_form.cube_name.$invalid && forms.cube_info_form.cube_name.$dirty && !forms.cube_info_form.cube_name.$error.required">Cube name is invalid.</small>
+
+                        <span ng-if="state.mode=='view'">{{cubeMetaFrame.name}}</span>
                     </div>
                 </div>
             </div>
-        </div>
 
-        <!--Notification-->
-        <div class="form-group">
-            <div class="row">
-                <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
-                    <b>Notification List</b>
-                </label>
-                <div class="col-xs-12 col-sm-6">
-                    <input type="text" class="form-control" placeholder="Comma Separated"
-                           ng-model="cubeMetaFrame.notify_list" ng-if="state.mode=='edit'" ng-list>
-                    <span ng-if="state.mode=='view'">{{cubeMetaFrame.notify_list}}</span>
+            <!--Notification-->
+            <div class="form-group">
+                <div class="row">
+                    <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
+                        <b>Notification List</b>
+                    </label>
+                    <div class="col-xs-12 col-sm-6">
+                        <input type="text" class="form-control" placeholder="Comma Separated"
+                               ng-model="cubeMetaFrame.notify_list" ng-if="state.mode=='edit'" ng-list>
+                        <span ng-if="state.mode=='view'">{{cubeMetaFrame.notify_list}}</span>
+                    </div>
                 </div>
             </div>
-        </div>
 
-        <!--Description-->
-        <div class="form-group">
-            <div class="row">
-                <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
-                    <b>Description</b>
-                </label>
-                <div class="col-xs-12 col-sm-6">
-                    <textarea ng-if="state.mode=='edit'" class="form-control box-default"
-                        name="comment" id="comment" ng-model="cubeMetaFrame.description"></textarea>
-                    <span ng-if="state.mode=='view'">{{cubeMetaFrame.description}}</span>
+            <!--Description-->
+            <div class="form-group">
+                <div class="row">
+                    <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
+                        <b>Description</b>
+                    </label>
+                    <div class="col-xs-12 col-sm-6">
+                        <textarea ng-if="state.mode=='edit'" class="form-control box-default"
+                            name="comment" id="comment" ng-model="cubeMetaFrame.description"></textarea>
+                        <span ng-if="state.mode=='view'">{{cubeMetaFrame.description}}</span>
+                    </div>
                 </div>
             </div>
-        </div>
+        </ng-form>
     </div>
 
     <!--Tips-->

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/partials/cubeDesigner/measures.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/measures.html b/webapp/app/partials/cubeDesigner/measures.html
index ef8c8bf..c426e95 100755
--- a/webapp/app/partials/cubeDesigner/measures.html
+++ b/webapp/app/partials/cubeDesigner/measures.html
@@ -17,65 +17,67 @@
 -->
 
 <!-- Measures Summary -->
-<div class="dataTables_wrapper form-inline no-footer" ng-if="cubeMetaFrame.measures.length > 0">
-    <div class="row">
-        <span class="nav-search input-icon input-icon-right" style="margin-left: 22px;">
-            <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="state.dimensionFilter"/>
-            <i class="ace-icon fa fa-search nav-search-icon"></i>
-        </span>
+<ng-form name="forms.cube_measure_form">
+    <div class="dataTables_wrapper form-inline no-footer" ng-if="cubeMetaFrame.measures.length > 0">
+            <div class="row">
+                <span class="nav-search input-icon input-icon-right" style="margin-left: 22px;">
+                    <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="state.dimensionFilter"/>
+                    <i class="ace-icon fa fa-search nav-search-icon"></i>
+                </span>
+            </div>
+            <table class="table table-striped table-hover">
+                <thead>
+                    <tr>
+                        <th>ID</th>
+                        <th>Name</th>
+                        <th>Expression</th>
+                        <th>Param Type</th>
+                        <th>Param Value</th>
+                        <th>Return Type</th>
+                        <th ng-if="state.mode=='edit'">Actions</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    <tr ng-repeat="measure in cubeMetaFrame.measures | filter: state.measureFilter track by $index">
+                        <td>
+                            <!--ID -->
+                            <b>{{measure.id = ($index + 1)}}</b>
+                        </td>
+                        <td>
+                            <!--Name -->
+                            <span tooltip="measure name..">{{measure.name}}</span>
+                        </td>
+                        <td>
+                            <!--Expression -->
+                            <span>{{measure.function.expression}}</span>
+                        </td>
+                        <td>
+                            <!--Param Type -->
+                            <span>{{measure.function.parameter.type}}</span>
+                        </td>
+                        <td>
+                            <!--Param Value -->
+                            <span>{{measure.function.parameter.value}}</span>
+                        </td>
+                        <td>
+                            <!--Return Type -->
+                            <span>{{measure.function.returntype}}</span>
+                        </td>
+                        <td ng-if="state.mode=='edit'">
+                            <!--Edit Button -->
+                            <button class="btn btn-xs btn-info" ng-click="addNewMeasure(measure)">
+                                <i class="fa fa-pencil"></i>
+                            </button>
+                            <!--Remove Button -->
+                            <button class="btn btn-xs  btn-danger" ng-click="removeElement(cubeMetaFrame.measures, measure)">
+                                <i class="fa fa-trash-o"></i>
+                            </button>
+                        </td>
+                    </tr>
+                </tbody>
+            </table>
     </div>
-    <table class="table table-striped table-hover">
-        <thead>
-            <tr>
-                <th>ID</th>
-                <th>Name</th>
-                <th>Expression</th>
-                <th>Param Type</th>
-                <th>Param Value</th>
-                <th>Return Type</th>
-                <th ng-if="state.mode=='edit'">Actions</th>
-            </tr>
-        </thead>
-        <tbody>
-            <tr ng-repeat="measure in cubeMetaFrame.measures | filter: state.measureFilter track by $index">
-                <td>
-                    <!--ID -->
-                    <b>{{measure.id = ($index + 1)}}</b>
-                </td>
-                <td>
-                    <!--Name -->
-                    <span tooltip="measure name..">{{measure.name}}</span>
-                </td>
-                <td>
-                    <!--Expression -->
-                    <span>{{measure.function.expression}}</span>
-                </td>
-                <td>
-                    <!--Param Type -->
-                    <span>{{measure.function.parameter.type}}</span>
-                </td>
-                <td>
-                    <!--Param Value -->
-                    <span>{{measure.function.parameter.value}}</span>
-                </td>
-                <td>
-                    <!--Return Type -->
-                    <span>{{measure.function.returntype}}</span>
-                </td>
-                <td ng-if="state.mode=='edit'">
-                    <!--Edit Button -->
-                    <button class="btn btn-xs btn-info" ng-click="addNewMeasure(measure)">
-                        <i class="fa fa-pencil"></i>
-                    </button>
-                    <!--Remove Button -->
-                    <button class="btn btn-xs  btn-danger" ng-click="removeElement(cubeMetaFrame.measures, measure)">
-                        <i class="fa fa-trash-o"></i>
-                    </button>
-                </td>
-            </tr>
-        </tbody>
-    </table>
-</div>
+</ng-form>
 
 <!--Add Measures Button-->
 <div class="form-group">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/partials/cubes/cube_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cube_schema.html b/webapp/app/partials/cubes/cube_schema.html
index 3fa16e5..6f3475c 100644
--- a/webapp/app/partials/cubes/cube_schema.html
+++ b/webapp/app/partials/cubes/cube_schema.html
@@ -28,7 +28,7 @@
                 <ul class="wizard-steps">
                     <li ng-repeat="step in wizardSteps"
                         class="{{step==curStep?'active':''}} {{step.isComplete?'complete':''}}">
-                        <span style="cursor:pointer;" ng-click="goToStep($index)" class="step">{{step.step = ($index + 1)}}</span>
+                        <span style="cursor:pointer;" ng-click="checkCubeForm()?goToStep($index):''" class="step">{{step.step = ($index + 1)}}</span>
                         <span class="title">{{step.title}}</span>
                      </li>
                 </ul>
@@ -41,7 +41,6 @@
             <div class="wizard-actions">
                 <div class="row">
                     <div class="col-xs-8">
-                        <p style="color: #808080;text-align: left;"><b>Note:</b> inputs with <span style="color: lightblue">light blue</span> border are mandatory.</p>
                         <div>
                             <a href="cubes" class="pull-left"><i class="fa fa-arrow-left"></i> Back to My Cubes</a>
                         </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/partials/modelDesigner/conditions_settings.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/conditions_settings.html b/webapp/app/partials/modelDesigner/conditions_settings.html
index 308e793..98ad8e3 100644
--- a/webapp/app/partials/modelDesigner/conditions_settings.html
+++ b/webapp/app/partials/modelDesigner/conditions_settings.html
@@ -19,7 +19,7 @@
 <div ng-controller="CubeRefreshCtrl">
 <div class="row">
     <div class="col-xs-8">
-
+      <ng-form name="forms.model_setting_form" novalidate>
         <!--Cube Partition Type-->
         <div class="form-group" ng-hide="true">
             <div class="row">
@@ -43,7 +43,6 @@
                 <div class="col-xs-12 col-sm-6">
 
                     <select style="width: 100%" chosen data-placeholder="e.g. DEFAULT.TEST_KYLIN_FACT.CAL_DT"
-                            ng-required="model.partition_desc.partition_date_start"
                             ng-model="model.partition_desc.partition_date_column"
                             ng-if="state.mode=='edit'"
                             data-placement=""
@@ -72,6 +71,21 @@
             </div>
         </div>
 
+          <div class="form-group" ng-show="userService.hasRole('ROLE_ADMIN')">
+              <div class="row">
+                  <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Cube Size</b></label>
+                  <div class="col-xs-12 col-sm-6">
+                      <select class="form-control"
+                              ng-if="state.mode=='edit'"
+                              chosen ng-model="model.capacity"
+                              ng-options="ddt as ddt for ddt in cubeConfig.cubeCapacities">
+                          <option value=""></option>
+                      </select>
+                      <span ng-if="state.mode=='view'">{{model.capacity}}</span>
+                  </div>
+              </div>
+          </div>
+
         <!--Filter Condition-->
         <div class="form-group">
             <div class="row">
@@ -103,6 +117,7 @@
                 </div>
             </div>
         </div>
+       </ng-form>
     </div>
 
     <div class="col-xs-4">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/partials/modelDesigner/model_dimensions.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/model_dimensions.html b/webapp/app/partials/modelDesigner/model_dimensions.html
index 10a8d77..095203d 100644
--- a/webapp/app/partials/modelDesigner/model_dimensions.html
+++ b/webapp/app/partials/modelDesigner/model_dimensions.html
@@ -18,87 +18,79 @@
 
 <div ng-controller="ModelDimensionsCtrl">
 
-<!-- Dimensions Summary -->
-<div class="dataTables_wrapper form-inline no-footer">
-    <div class="row"  ng-if="state.mode=='view'&&model.dimensions.length > 0">
-        <div class="col-xs-6">
-            <b>Dimensions</b>
+    <!-- Dimensions Summary -->
+    <div class="dataTables_wrapper form-inline no-footer">
+        <div class="row"  ng-if="state.mode=='view'&&model.dimensions.length > 0">
+            <div class="col-xs-6">
+                <b>Dimensions</b>
+            </div>
+            <div class="col-xs-6">
+                <span class="pull-right input-icon input-icon-right nav-search" style="margin-left: 22px;">
+                    <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="dimState.filter"/>
+                    <i class="ace-icon fa fa-search nav-search-icon"></i>
+                </span>
+            </div>
         </div>
-        <div class="col-xs-6">
-            <span class="pull-right input-icon input-icon-right nav-search" style="margin-left: 22px;">
-                <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="dimState.filter"/>
-                <i class="ace-icon fa fa-search nav-search-icon"></i>
-            </span>
-        </div>
-    </div>
 
-    <ng-form name="model_dimensions" novalidate>
-     <!-- VIEW MODE -->
-        <table class="table table-striped table-hover" ng-if="state.mode=='view'&&model.dimensions.length > 0">
-            <thead>
-                <tr>
-                    <th>ID</th>
-                    <th>Table Name</th>
-                    <th>Columns</th>
+        <ng-form name="forms.model_dimensions_form" novalidate>
+         <!-- VIEW MODE -->
+            <table class="table table-striped table-hover" ng-if="state.mode=='view'&&model.dimensions.length > 0">
+                <thead>
+                    <tr>
+                        <th>ID</th>
+                        <th>Table Name</th>
+                        <th>Columns</th>
+                    </tr>
+                </thead>
+                <tbody class="cube-dimension">
+                    <tr ng-repeat="dimension in model.dimensions | filter:dimState.filter track by $index">
+                        <!--ID -->
+                        <td>
+                            <b>{{dimension.id = ($index + 1)}}</b>
+                        </td>
+                        <!--Name -->
+                        <td>
+                            <span>{{dimension.table}}</span>
+                        </td>
+                        <!--Table Name -->
+                        <td>
+                            <span>{{dimension.columns}}</span>
+                        </td>
+                    </tr>
+                </tbody>
+            </table>
+        </ng-form>
+        <div  ng-if="state.mode=='edit'" class="form-group model-dimension-edit" style="width: 100%">
+            <h4 style="margin-left:42px">Dimensions</h4>
+            <table style="margin-left:42px; width:92%"
+                   ng-if="model.dimensions.length > 0"
+                   class="table table-hover list">
+                <tr class="row">
+                    <th class="col-xs-1">ID</th>
+                    <th class="col-xs-2">Table Name</th>
+                    <th class="col-xs-9">Columns</th>
                 </tr>
-            </thead>
-            <tbody class="cube-dimension">
-                <tr ng-repeat="dimension in model.dimensions | filter:dimState.filter track by $index">
-                    <!--ID -->
-                    <td>
-                        <b>{{dimension.id = ($index + 1)}}</b>
+
+                <tr ng-repeat="dimension in model.dimensions" class="row">
+                    <td class="col-xs-1">
+                        <!-- ID -->
+                        <b>{{($index + 1)}}</b>
                     </td>
-                    <!--Name -->
-                    <td>
-                        <span>{{dimension.table}}</span>
+                    <td class="col-xs-2">
+                            {{dimension.table}}
                     </td>
-                    <!--Table Name -->
-                    <td>
-                        <span>{{dimension.columns}}</span>
+                    <td class="col-xs-9">
+                        <!-- Dimensions -->
+                        <select ng-if="state.mode=='edit'" style="width: 100%"
+                                ng-model="model.dimensions[$index].columns" required chosen multiple
+                                ng-change=""
+                                ng-options="column.name as column.name for column in getColumnsByTable(dimension.table)">
+                            <option value=""></option>
+                        </select>
                     </td>
                 </tr>
-            </tbody>
-        </table>
-    </ng-form>
-    <div  ng-if="state.mode=='edit'" class="form-group model-dimension-edit" style="width: 100%">
-        <h4 style="margin-left:42px">Dimensions</h4>
-        <table style="margin-left:42px; width:92%"
-               ng-if="model.dimensions.length > 0"
-               class="table table-hover list">
-            <tr class="row">
-                <th class="col-xs-1">ID</th>
-                <th class="col-xs-1">Table Name</th>
-                <th class="col-xs-9">Columns</th>
-                <th class="col-xs-1"></th>
-            </tr>
-
-            <tr ng-repeat="dimension in model.dimensions" class="row">
-                <td class="col-xs-1">
-                    <!-- ID -->
-                    <b>{{($index + 1)}}</b>
-                </td>
-                <td class="col-xs-1">
-                        {{dimension.table}}
-                </td>
-                <td class="col-xs-9">
-                    <!-- Dimensions -->
-                    <select ng-if="state.mode=='edit'" style="width: 100%"
-                            ng-model="model.dimensions[$index].columns" required chosen multiple
-                            ng-change=""
-                            ng-options="column.name as column.name for column in getColumnsByTable(dimension.table)">
-                        <option value=""></option>
-                    </select>
-                </td>
-                <td class="col-xs-1">
-                    <button class="btn btn-xs btn-info"
-                            ng-click="removeTableDimensions($index)"><i
-                            class="fa fa-minus"></i>
-                    </button>
-                </td>
-            </tr>
-        </table>
+            </table>
+         </div>
 
-
-</div>
-
-</div>
+    </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/partials/modelDesigner/model_measures.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/model_measures.html b/webapp/app/partials/modelDesigner/model_measures.html
index 9451569..f324788 100644
--- a/webapp/app/partials/modelDesigner/model_measures.html
+++ b/webapp/app/partials/modelDesigner/model_measures.html
@@ -17,6 +17,7 @@
 -->
 
 <!-- Measures Summary -->
+<ng-form name="forms.model_measure_form" novalidate>
 <div class="dataTables_wrapper form-inline no-footer">
 
     <table ng-if="state.mode=='view'&&model.metrics.length > 0" class="table table-striped table-hover">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/992fd74f/webapp/app/partials/models/model_schema.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/model_schema.html b/webapp/app/partials/models/model_schema.html
index 86a3196..2f58bed 100644
--- a/webapp/app/partials/models/model_schema.html
+++ b/webapp/app/partials/models/model_schema.html
@@ -50,12 +50,12 @@
                             <i class="ace-icon fa fa-arrow-left"></i>
                             Prev
                         </button>
-                        <button id="nextButton" class="btn btn-success btn-next"  ng-click="checkForm()?nextView():''" ng-disabled="design_form.$invalid"
+                        <button id="nextButton" class="btn btn-success btn-next"  ng-click="checkForm()?nextView():''"
                                 ng-show="curStep.title!='Settings'">
                             Next
                             <i class="ace-icon fa fa-arrow-right icon-on-right"></i>
                         </button>
-                        <button class="btn btn-primary" ng-click="prepareModel();saveModel(design_form)" ng-disabled="design_form.$invalid"
+                        <button class="btn btn-primary" ng-click="prepareModel();saveModel()"
                                 ng-if="curStep.title=='Settings' && state.mode=='edit'">
                             Save
                         </button>