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:03 UTC

[34/52] [abbrv] incubator-kylin git commit: step check enhance

step check enhance


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

Branch: refs/heads/0.8.0
Commit: aebd109efce17c0d826d362d653dfda3dd0639cb
Parents: 992fd74
Author: jiazhong <ji...@ebay.com>
Authored: Wed Apr 1 19:37:15 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:53 2015 +0800

----------------------------------------------------------------------
 webapp/app/js/controllers/cubeDimensions.js     |   4 +-
 webapp/app/js/controllers/cubeEdit.js           |   5 +-
 webapp/app/js/controllers/cubeSchema.js         |  46 +++-
 webapp/app/js/controllers/modelEdit.js          |  12 +-
 webapp/app/js/controllers/modelSchema.js        |   6 +
 webapp/app/js/controllers/models.js             |   1 -
 webapp/app/js/controllers/projectMeta.js        |   3 +-
 webapp/app/js/model/metaModel.js                |   8 +-
 webapp/app/js/model/tableModel.js               |   3 +-
 .../cubeDesigner/advanced_settings.html         | 236 ++++++++++---------
 webapp/app/partials/cubeDesigner/info.html      |  16 +-
 webapp/app/partials/cubes/cube_schema.html      |   8 +-
 webapp/app/partials/header.html                 |   4 +-
 .../modelDesigner/conditions_settings.html      |   8 +-
 .../app/partials/modelDesigner/data_model.html  |  15 +-
 .../modelDesigner/model_dimensions.html         |  12 +-
 .../app/partials/modelDesigner/model_info.html  |  27 +--
 webapp/app/partials/models/model_schema.html    |   8 +-
 .../partials/projects/project_table_tree.html   |   2 +-
 19 files changed, 232 insertions(+), 192 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/js/controllers/cubeDimensions.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeDimensions.js b/webapp/app/js/controllers/cubeDimensions.js
index f114ccb..35b66ab 100644
--- a/webapp/app/js/controllers/cubeDimensions.js
+++ b/webapp/app/js/controllers/cubeDimensions.js
@@ -106,7 +106,9 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel) {
 
             $scope.availableColumns[lookups[j].table] = lookupAvailable;
             $scope.selectedColumns[lookups[j].table] = lookupSelectAvailable;
-            $scope.availableTables.push(lookups[j].table);
+            if($scope.availableTables.indexOf(lookups[j].table)==-1){
+                $scope.availableTables.push(lookups[j].table);
+            }
         }
     };
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/js/controllers/cubeEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeEdit.js b/webapp/app/js/controllers/cubeEdit.js
index 2bbdd05..98fc9a3 100755
--- a/webapp/app/js/controllers/cubeEdit.js
+++ b/webapp/app/js/controllers/cubeEdit.js
@@ -181,7 +181,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         return $interpolate($templateCache.get(tmpl))(notification);
     };
 
-    $scope.saveCube = function (design_form) {
+    $scope.saveCube = function () {
 
         try {
             angular.fromJson($scope.state.cubeSchema);
@@ -208,9 +208,6 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
                             $scope.state.cubeSchema = request.cubeDescData;
                             MessageService.sendMsg($scope.cubeResultTmpl({'text':'Updated the cube successfully.',type:'success'}), 'success', {}, true, 'top_center');
 
-                            if (design_form) {
-                                design_form.$invalid = true;
-                            }
                         } else {
                             $scope.saveCubeRollBack();
                             $scope.cubeMetaFrame.project = $scope.state.project;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/js/controllers/cubeSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeSchema.js b/webapp/app/js/controllers/cubeSchema.js
index a3bbd89..327dc25 100755
--- a/webapp/app/js/controllers/cubeSchema.js
+++ b/webapp/app/js/controllers/cubeSchema.js
@@ -32,7 +32,7 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
     if (UserService.hasRole("ROLE_ADMIN")) {
             $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,form:'cube_overview_form'});
+    $scope.wizardSteps.push({title: 'Overview', src: 'partials/cubeDesigner/overview.html', isComplete: false,form:null});
 
     $scope.curStep = $scope.wizardSteps[0];
 
@@ -157,6 +157,11 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
     };
 
     $scope.goToStep = function(stepIndex){
+        if($scope.state.mode=="edit"){
+            if(stepIndex+1>=$scope.curStep.step){
+                return;
+            }
+        }
         for(var i=0;i<$scope.wizardSteps.length;i++){
             if(i<=stepIndex){
                 $scope.wizardSteps[i].isComplete = true;
@@ -183,6 +188,7 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
         else{
             //form validation
             if($scope.forms[$scope.curStep.form].$invalid){
+                $scope.forms[$scope.curStep.form].$submitted = true;
                 return false;
             }else{
                 //business rule check
@@ -193,6 +199,8 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
                     case 'cube_measure_form':
                         return $scope.check_cube_measure();
                         break;
+                    case 'cube_setting_form':
+                        return $scope.check_cube_setting();
                     default:
                         return true;
                         break;
@@ -220,10 +228,44 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
     };
 
     $scope.check_cube_measure = function(){
+        var _measures = $scope.cubeMetaFrame.measures;
         var errors = [];
-        if(!$scope.cubeMetaFrame.measures||!$scope.cubeMetaFrame.measures.length){
+        if(!_measures||!_measures.length){
             errors.push("Please define your metrics.");
         }
+
+        var existCountExpression = false;
+        for(var i=0;i<_measures.length;i++){
+            if(_measures[i].function.expression=="COUNT"){
+                existCountExpression=true;
+                break;
+            }
+        }
+        if(!existCountExpression){
+            errors.push("[COUNT] metric is required.");
+        }
+
+        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_setting = function(){
+        var errors = [];
+
+        angular.forEach($scope.cubeMetaFrame.rowkey.aggregation_groups,function(group){
+            if(!group.length){
+                errors.push("Each aggregation group can't be empty.");
+            }
+        })
+
         var errorInfo = "";
         angular.forEach(errors,function(item){
             errorInfo+="\n"+item;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/js/controllers/modelEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelEdit.js b/webapp/app/js/controllers/modelEdit.js
index 8e676d2..810242e 100644
--- a/webapp/app/js/controllers/modelEdit.js
+++ b/webapp/app/js/controllers/modelEdit.js
@@ -23,8 +23,13 @@ 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;
 
+    if($scope.modelMode=="addNewModel"&&!ProjectModel.getSelectedProject()){
+        SweetAlert.swal('Oops...', 'Please select your project first.', 'warning');
+        $location.path("/models");
+    }
+
+    $scope.cubeConfig = cubeConfig;
 
     $scope.getPartitonColumns = function(tableName){
         var columns = _.filter($scope.getColumnsByTable(tableName),function(column){
@@ -96,10 +101,11 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
         $scope.model.project = ProjectModel.getSelectedProject();
     }
 
+
     $scope.prepareModel = function () {
         // generate column family
 
-        if ($scope.model.partition_desc.partition_date_column&&($scope.model.partition_desc.partition_date_start|$scope.model.partition_desc.partition_date_start==0)) {
+        if ($scope.model.partition_desc.partition_date_column!=null&&($scope.model.partition_desc.partition_date_start|$scope.model.partition_desc.partition_date_start==0)) {
             var dateStart = new Date($scope.model.partition_desc.partition_date_start);
             dateStart = (dateStart.getFullYear() + "-" + (dateStart.getMonth() + 1) + "-" + dateStart.getDate());
             //switch selected time to utc timestamp
@@ -126,6 +132,8 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
 
     $scope.saveModel = function () {
 
+        $scope.prepareModel();
+
         try {
             angular.fromJson($scope.state.modelSchema);
         } catch (e) {

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/js/controllers/modelSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelSchema.js b/webapp/app/js/controllers/modelSchema.js
index 2ec1fa7..409582a 100644
--- a/webapp/app/js/controllers/modelSchema.js
+++ b/webapp/app/js/controllers/modelSchema.js
@@ -105,6 +105,7 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
         else{
             //form validation
             if($scope.forms[$scope.curStep.form].$invalid){
+                $scope.forms[$scope.curStep.form].$sbumitted=true;
                 return false;
             }else{
                 //business rule check
@@ -222,6 +223,11 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
 
 
     $scope.goToStep = function(stepIndex){
+        if($scope.state.mode=="edit"){
+            if(stepIndex+1>=$scope.curStep.step){
+                return;
+            }
+        }
         for(var i=0;i<$scope.wizardSteps.length;i++){
             if(i<=stepIndex){
                 $scope.wizardSteps[i].isComplete = true;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/js/controllers/models.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/models.js b/webapp/app/js/controllers/models.js
index e9e942f..20ccffb 100644
--- a/webapp/app/js/controllers/models.js
+++ b/webapp/app/js/controllers/models.js
@@ -31,7 +31,6 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
 
         $scope.toggleTab = function(showModel){
             $scope.showModels = showModel;
-            console.log($scope.showModels);
         }
 
         $scope.modelList = ModelList;

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/js/controllers/projectMeta.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/projectMeta.js b/webapp/app/js/controllers/projectMeta.js
index 9ca2092..d0e8781 100644
--- a/webapp/app/js/controllers/projectMeta.js
+++ b/webapp/app/js/controllers/projectMeta.js
@@ -60,9 +60,8 @@ KylinApp
                         }
                     }
 
+                    var _table_node_list = [];
                     angular.forEach(tables,function(_table){
-                            var _table_node_list = [];
-
                             var _table_node = {
                                 label:_table.name,
                                 data:_table,

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/js/model/metaModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/metaModel.js b/webapp/app/js/model/metaModel.js
index 28e9f69..5366809 100644
--- a/webapp/app/js/model/metaModel.js
+++ b/webapp/app/js/model/metaModel.js
@@ -31,8 +31,8 @@ KylinApp.service('MetaModel',function(){
         dimensions:[],
         metrics:[],
         "partition_desc" : {
-            "partition_date_column" : '',
-            "partition_date_start" : 0,
+            "partition_date_column" : null,
+            "partition_date_start" : null,
             "partition_type" : 'APPEND'
         },
         last_modified:0
@@ -82,8 +82,8 @@ KylinApp.service('MetaModel',function(){
             dimensions:[],
             metrics:[],
             "partition_desc" : {
-                "partition_date_column" : '',
-                "partition_date_start" : 0,
+                "partition_date_column" : null,
+                "partition_date_start" : null,
                 "partition_type" : 'APPEND'
             },
             last_modified:0

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/js/model/tableModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/tableModel.js b/webapp/app/js/model/tableModel.js
index 55b4e7b..d3bc026 100755
--- a/webapp/app/js/model/tableModel.js
+++ b/webapp/app/js/model/tableModel.js
@@ -99,8 +99,8 @@ KylinApp.service('TableModel', function(ProjectModel,$q,TableService,$log) {
                     }
                 }
 
+                var _table_node_list = [];
                 angular.forEach(tables,function(_table){
-                        var _table_node_list = [];
 
                         var _table_node = {
                             label:_table.name,
@@ -120,6 +120,7 @@ KylinApp.service('TableModel', function(ProjectModel,$q,TableService,$log) {
                                     onSelect:function(branch){
                                         // set selected model
 //                                        _this.selectedSrcTable = branch.data;
+                                        _this.selectedSrcTable.selectedSrcColumn = branch.data;
                                         $log.info("selected column info:"+_column.name);
                                     }
                                 });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/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 cb2eaed..ba2e20d 100755
--- a/webapp/app/partials/cubeDesigner/advanced_settings.html
+++ b/webapp/app/partials/cubeDesigner/advanced_settings.html
@@ -17,132 +17,134 @@
 -->
 
 <div ng-controller="CubeAdvanceSettingCtrl">
-<div>
-    <div class="form-group">
-        <h4 style="margin-left:42px">Aggregation Groups</h4>
-        <table style="margin-left:42px; width:92%"
-               ng-if="cubeMetaFrame.rowkey.aggregation_groups.length > 0"
-               class="table table-hover list">
-            <tr class="row">
-                <th class="col-xs-1">ID</th>
-                <th class="col-xs-10">Aggregation Groups</th>
-                <th ng-if="state.mode=='edit'" class="col-xs-1"></th>
-            </tr>
-
-            <tr ng-repeat="aggregation_groups in cubeMetaFrame.rowkey.aggregation_groups" class="row">
-                <td class="col-xs-1">
-                    <!-- ID -->
-                    <b>{{($index + 1)}}</b>
-                </td>
-                <td class="col-xs-11">
-                    <!-- Dimensions -->
-                    <select ng-if="state.mode=='edit'" style="width: 100%"
-                            ng-model="aggregation_groups" required chosen multiple
-                            ng-change="refreshAggregationGroup(cubeMetaFrame.rowkey.aggregation_groups, $index, aggregation_groups)"
-                            ng-options="rowkey_column.column as rowkey_column.column for rowkey_column in cubeMetaFrame.rowkey.rowkey_columns">
-                        <option value=""></option>
-                    </select>
-                    <p ng-if="state.mode=='view'" style="word-wrap: break-word; word-break: normal;max-width: 1000px ">{{aggregation_groups}}</p>
-                </td>
-                <td ng-if="state.mode=='edit'" class="col-xs-1">
-                    <button class="btn btn-xs btn-info"
-                            ng-click="removeElement(cubeMetaFrame.rowkey.aggregation_groups, aggregation_groups)"><i
-                            class="fa fa-minus"></i>
-                    </button>
-                </td>
-            </tr>
-        </table>
-
-        <button class="btn btn-sm btn-info" style="margin-left:42px" ng-click="addNewAggregationGroup()"
-                ng-show="state.mode=='edit'">New Aggregation Group<i class="fa fa-plus"></i>
-        </button>
-
-
-    </div>
-
-
-    <div class="form-group">
-        <h4 style="margin-left:42px">Rowkeys</h4>
-        <table style="margin-left:42px; width:92%"
-               ng-if="cubeMetaFrame.rowkey.rowkey_columns.length > 0"
-               class="table table-hover list"
-                >
-           <thead>
-                <tr>
-                    <th>ID</th>
-                    <th>Column</th>
-                    <th>Mandatory</th>
-                    <th>Dictionary</th>
-                    <th>Length</th>
-                    <th ng-if="state.mode=='edit'"></th>
+  <ng-form name="forms.cube_setting_form">
+    <div>
+        <div class="form-group">
+            <h4 style="margin-left:42px">Aggregation Groups</h4>
+            <table style="margin-left:42px; width:92%"
+                   ng-if="cubeMetaFrame.rowkey.aggregation_groups.length > 0"
+                   class="table table-hover list">
+                <tr class="row">
+                    <th class="col-xs-1">ID</th>
+                    <th class="col-xs-10">Aggregation Groups</th>
+                    <th ng-if="state.mode=='edit'" class="col-xs-1"></th>
                 </tr>
-           </thead>
 
-            <tbody ui-sortable="state.mode=='edit'" ng-model="cubeMetaFrame.rowkey.rowkey_columns">
-
-                <tr  ng-repeat="rowkey_column in cubeMetaFrame.rowkey.rowkey_columns" ng-class="state.mode=='edit'?'sort-item':''">
-
-                    <td>
+                <tr ng-repeat="aggregation_groups in cubeMetaFrame.rowkey.aggregation_groups" class="row">
+                    <td class="col-xs-1">
                         <!-- ID -->
-                        <span class="ng-binding" ng-class="state.mode=='edit'?'badge':''">{{($index + 1)}}</span>
-                    </td>
-                    <td>
-                        <!--Column Name -->
-                        <input type="text" class="form-control" placeholder="Column Name.." ng-if="state.mode=='edit'"
-                               tooltip="rowkey column name.." tooltip-trigger="focus"
-                               ng-model="rowkey_column.column" class="form-control">
-
-                        <span ng-if="state.mode=='view'">{{rowkey_column.column}}</span>
-                    </td>
-                    <td>
-                        <!-- Mandatory -->
-                        <button type="button " ng-if="state.mode=='edit'"
-                                class="btn btn-xs btn-default {{rowkey_column.mandatory? 'active':''}}"
-                                ng-model="rowkey_column.mandatory"
-                                ng-click="updateMandatory(rowkey_column);"
-                                btn-checkbox btn-checkbox-true="true" btn-checkbox-false="false">
-                            {{rowkey_column.mandatory? 'Y':'N'}}
-                        </button>
-
-                        <span ng-if="state.mode=='view'">{{rowkey_column.mandatory? 'Y':'N'}}</span>
+                        <b>{{($index + 1)}}</b>
                     </td>
-
-                    <td>
-                        <!--Use Dictionary-->
-                        <div>
-                            <select ng-if="state.mode=='edit'" style="width:80px;"
-                                    chosen ng-model="rowkey_column.dictionary"
-                                    ng-change="dictionaryUpdated(rowkey_column);"
-                                    ng-options="dt as dt for dt in cubeConfig.dictionaries">
-                                <option value=""></option>
-                            </select>
-                            <span ng-if="state.mode=='view'">{{rowkey_column.dictionary}}</span>
-                        </div>
-                    </td>
-
-                    <td>
-                        <!--Column Length -->
-                        <input type="text" class="form-control" placeholder="Column Length.." ng-if="state.mode=='edit'"
-                               tooltip="rowkey column length.." tooltip-trigger="focus"
-                               ng-disabled="rowkey_column.dictionary=='true'"
-                               ng-model="rowkey_column.length"  class="form-control">
-
-                        <span ng-if="state.mode=='view'">{{rowkey_column.length}}</span>
+                    <td class="col-xs-11">
+                        <!-- Dimensions -->
+                        <select ng-if="state.mode=='edit'" style="width: 100%"
+                                ng-model="aggregation_groups"  chosen multiple
+                                ng-change="refreshAggregationGroup(cubeMetaFrame.rowkey.aggregation_groups, $index, aggregation_groups)"
+                                ng-options="rowkey_column.column as rowkey_column.column for rowkey_column in cubeMetaFrame.rowkey.rowkey_columns">
+                            <option value=""></option>
+                        </select>
+                        <p ng-if="state.mode=='view'" style="word-wrap: break-word; word-break: normal;max-width: 1000px ">{{aggregation_groups}}</p>
                     </td>
-
-
-                    <td ng-if="state.mode=='edit'">
+                    <td ng-if="state.mode=='edit'" class="col-xs-1">
                         <button class="btn btn-xs btn-info"
-                                ng-click="removeElement(cubeMetaFrame.rowkey.rowkey_columns, rowkey_column)"><i
+                                ng-click="removeElement(cubeMetaFrame.rowkey.aggregation_groups, aggregation_groups)"><i
                                 class="fa fa-minus"></i>
                         </button>
                     </td>
                 </tr>
-            </tbody>
-        </table>
-
-        <button class="btn btn-sm btn-info" style="margin-left:42px"
-                ng-click="addNewRowkeyColumn()" ng-show="state.mode=='edit'">New Rowkey Column<i class="fa fa-plus"></i></button>
+            </table>
+
+            <button class="btn btn-sm btn-info" style="margin-left:42px" ng-click="addNewAggregationGroup()"
+                    ng-show="state.mode=='edit'">New Aggregation Group<i class="fa fa-plus"></i>
+            </button>
+
+
+        </div>
+
+
+        <div class="form-group">
+            <h4 style="margin-left:42px">Rowkeys</h4>
+            <table style="margin-left:42px; width:92%"
+                   ng-if="cubeMetaFrame.rowkey.rowkey_columns.length > 0"
+                   class="table table-hover list"
+                    >
+               <thead>
+                    <tr>
+                        <th>ID</th>
+                        <th>Column</th>
+                        <th>Mandatory</th>
+                        <th>Dictionary</th>
+                        <th>Length</th>
+                        <th ng-if="state.mode=='edit'"></th>
+                    </tr>
+               </thead>
+
+                <tbody ui-sortable="state.mode=='edit'" ng-model="cubeMetaFrame.rowkey.rowkey_columns">
+
+                    <tr  ng-repeat="rowkey_column in cubeMetaFrame.rowkey.rowkey_columns" ng-class="state.mode=='edit'?'sort-item':''">
+
+                        <td>
+                            <!-- ID -->
+                            <span class="ng-binding" ng-class="state.mode=='edit'?'badge':''">{{($index + 1)}}</span>
+                        </td>
+                        <td>
+                            <!--Column Name -->
+                            <input type="text" class="form-control" placeholder="Column Name.." ng-if="state.mode=='edit'"
+                                   tooltip="rowkey column name.." tooltip-trigger="focus"
+                                   ng-model="rowkey_column.column" class="form-control">
+
+                            <span ng-if="state.mode=='view'">{{rowkey_column.column}}</span>
+                        </td>
+                        <td>
+                            <!-- Mandatory -->
+                            <button type="button " ng-if="state.mode=='edit'"
+                                    class="btn btn-xs btn-default {{rowkey_column.mandatory? 'active':''}}"
+                                    ng-model="rowkey_column.mandatory"
+                                    ng-click="updateMandatory(rowkey_column);"
+                                    btn-checkbox btn-checkbox-true="true" btn-checkbox-false="false">
+                                {{rowkey_column.mandatory? 'Y':'N'}}
+                            </button>
+
+                            <span ng-if="state.mode=='view'">{{rowkey_column.mandatory? 'Y':'N'}}</span>
+                        </td>
+
+                        <td>
+                            <!--Use Dictionary-->
+                            <div>
+                                <select ng-if="state.mode=='edit'" style="width:80px;"
+                                        chosen ng-model="rowkey_column.dictionary"
+                                        ng-change="dictionaryUpdated(rowkey_column);"
+                                        ng-options="dt as dt for dt in cubeConfig.dictionaries">
+                                    <option value=""></option>
+                                </select>
+                                <span ng-if="state.mode=='view'">{{rowkey_column.dictionary}}</span>
+                            </div>
+                        </td>
+
+                        <td>
+                            <!--Column Length -->
+                            <input type="text" class="form-control" placeholder="Column Length.." ng-if="state.mode=='edit'"
+                                   tooltip="rowkey column length.." tooltip-trigger="focus"
+                                   ng-disabled="rowkey_column.dictionary=='true'"
+                                   ng-model="rowkey_column.length"  class="form-control">
+
+                            <span ng-if="state.mode=='view'">{{rowkey_column.length}}</span>
+                        </td>
+
+
+                        <td ng-if="state.mode=='edit'">
+                            <button class="btn btn-xs btn-info"
+                                    ng-click="removeElement(cubeMetaFrame.rowkey.rowkey_columns, rowkey_column)"><i
+                                    class="fa fa-minus"></i>
+                            </button>
+                        </td>
+                    </tr>
+                </tbody>
+            </table>
+
+            <button class="btn btn-sm btn-info" style="margin-left:42px"
+                    ng-click="addNewRowkeyColumn()" ng-show="state.mode=='edit'">New Rowkey Column<i class="fa fa-plus"></i></button>
+        </div>
     </div>
-</div>
+  </ng-form>
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/partials/cubeDesigner/info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/info.html b/webapp/app/partials/cubeDesigner/info.html
index d724ffd..1833818 100644
--- a/webapp/app/partials/cubeDesigner/info.html
+++ b/webapp/app/partials/cubeDesigner/info.html
@@ -25,10 +25,14 @@
                     <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"
+                    <div class="col-xs-12 col-sm-6" ng-class="{'has-error':forms.cube_info_form.model_name.$invalid && (forms.cube_info_form.model_name.$dirty||forms.cube_info_form.$sbumitted)}">
+                        <input disabled ng-if="state.mode=='edit'" name="model_name" type="text" required class="form-control"
+                               placeholder="You can use letters, numbers, and '_'"
+                               ng-maxlength=100 ng-pattern="/^\w+$/"
                                ng-model="cubeMetaFrame.model_name"/>
-                        <small class="help-block" ng-show="forms.cube_info_form.model_name.$error.required">The model is required</small>
+                        <small class="help-block" ng-show="forms.cube_info_form.model_name.$error.required && (forms.cube_info_form.model_name.$dirty||forms.cube_info_form.$sbumitted)">Model name is required.</small>
+                        <small class="help-block" ng-show="!forms.cube_info_form.model_name.$error.required&&forms.cube_info_form.model_name.$invalid && (forms.cube_info_form.model_name.$dirty||forms.cube_info_form.$sbumitted)">Model name is invalid.</small>
+
                         <span ng-if="state.mode=='view'">
                             {{cubeMetaFrame.model_name}}
                         </span>
@@ -42,13 +46,13 @@
                     <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':''">
+                    <div class="col-xs-12 col-sm-6" ng-class="{'has-error':forms.cube_info_form.cube_name.$invalid && (forms.cube_info_form.cube_name.$dirty||forms.cube_info_form.cube_name.$sbumitted)}">
                         <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>
+                        <small class="help-block" ng-show="forms.cube_info_form.cube_name.$error.required && (forms.cube_info_form.cube_name.$dirty||forms.cube_info_form.$sbumitted)">Cube name is required.</small>
+                        <small class="help-block" ng-show="!forms.cube_info_form.cube_name.$error.required&&forms.cube_info_form.cube_name.$invalid && (forms.cube_info_form.cube_name.$dirty||forms.cube_info_form.$sbumitted)">Cube name is invalid.</small>
 
                         <span ng-if="state.mode=='view'">{{cubeMetaFrame.name}}</span>
                     </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/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 6f3475c..b35e31a 100644
--- a/webapp/app/partials/cubes/cube_schema.html
+++ b/webapp/app/partials/cubes/cube_schema.html
@@ -21,9 +21,6 @@
         <h4 class="box-title text-info">Cube Designer</h4>
     </div>
     <div class="box-body">
-        <ng-form name="design_form" ng-submit="">
-            <!-- Add a mock button to avoid auto submit-->
-            <button ng-click="" ng-show="false"></button>
             <div>
                 <ul class="wizard-steps">
                     <li ng-repeat="step in wizardSteps"
@@ -50,18 +47,17 @@
                             <i class="ace-icon fa fa-arrow-left"></i>
                             Prev
                         </button>
-                        <button id="nextButton" class="btn btn-success btn-next"  ng-click="nextView()" ng-disabled="design_form.$invalid"
+                        <button id="nextButton" class="btn btn-success btn-next"  ng-click="checkCubeForm()?nextView():''" ng-disabled="forms[curStep.form].$invalid"
                                 ng-show="curStep.title!='Overview'">
                             Next
                             <i class="ace-icon fa fa-arrow-right icon-on-right"></i>
                         </button>
-                        <button class="btn btn-primary" ng-click="prepareCube();saveCube(design_form)" ng-disabled="design_form.$invalid"
+                        <button class="btn btn-primary" ng-click="prepareCube();saveCube()" ng-disabled="design_form.$invalid"
                                 ng-if="curStep.title=='Overview' && state.mode=='edit'">
                             Save
                         </button>
                     </div>
                 </div>
             </div>
-        </ng-form>
     </div>
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/partials/header.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/header.html b/webapp/app/partials/header.html
index 43bf27d..bac16cd 100644
--- a/webapp/app/partials/header.html
+++ b/webapp/app/partials/header.html
@@ -26,7 +26,7 @@
                     <span class="icon-bar"></span>
                     <span class="icon-bar"></span>
                 </button>
-                <a class="navbar-brand" href="home" style="padding: 2px 10px 0px 0px"><img src="image/logo.png" height="40px" width="40px"/><small> Kylin </small></a>
+                <a class="navbar-brand" href="query" style="padding: 2px 10px 0px 0px"><img src="image/logo.png" height="40px" width="40px"/><small> Kylin </small></a>
             </div>
 
             <div class="navbar-collapse collapse" collapse="isCollapsed">
@@ -34,7 +34,7 @@
                     <li class="project-cntnr"  style="padding:7px 15px;background-color:#2e8965;" ng-if="userService.isAuthorized()">
                         <select chosen ng-model="projectModel.selectedProject" ng-init="newAccess.permission=permissions.READ.value;"
                                 ng-options="project.name as project.name for project in projectModel.projects"
-                                style="width: 150px"
+                                style="width: 180px"
                                 data-placeholder="select a project"
                                 class="chosen-select">
                             <option ng-if="userService.hasRole('ROLE_ADMIN')" ng-selected="projectModel.selectedProject==null"  value=""> -- Choose Project -- </option>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/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 98ad8e3..035c777 100644
--- a/webapp/app/partials/modelDesigner/conditions_settings.html
+++ b/webapp/app/partials/modelDesigner/conditions_settings.html
@@ -40,7 +40,7 @@
         <div class="form-group">
             <div class="row">
                 <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Partition Date Column</b></label>
-                <div class="col-xs-12 col-sm-6">
+                <div class="col-xs-12 col-sm-6" ng-class="model.partition_desc.partition_date_column==null&& model.partition_desc.partition_date_start!=null?'has-error':''">
 
                     <select style="width: 100%" chosen data-placeholder="e.g. DEFAULT.TEST_KYLIN_FACT.CAL_DT"
                             ng-model="model.partition_desc.partition_date_column"
@@ -49,7 +49,9 @@
                             ng-options="model.fact_table+'.'+columns.name as model.fact_table+'.'+columns.name for columns in getPartitonColumns(model.fact_table)" >
                         <option value="">--Select Partition Column--</option>
                     </select>
+                    <small class="help-block" ng-show="model.partition_desc.partition_date_column==null&& model.partition_desc.partition_date_start!=null">Please select your partitoin date column.</small>
                     <p class="text-red"  ng-if="state.mode=='edit'">(data format in column should be 'YYYY-MM-DD')</p>
+
                     <span ng-if="state.mode=='view'">
                         {{!!(model.partition_desc.partition_date_column)?model.partition_desc.partition_date_column: ''}}</span>
                 </div>
@@ -60,11 +62,12 @@
         <div class="form-group">
             <div class="row">
                 <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Start Date</b></label>
-                <div class="col-xs-12 col-sm-6">
+                <div class="col-xs-12 col-sm-6" ng-class="model.partition_desc.partition_date_column!=null&& model.partition_desc.partition_date_start==null?'has-error':''">
                   <!--edit model will convert in MetaModel.converDateToGMT-->
                     <input type="text" class="form-control" datepicker-popup="yyyy-MM-dd"
                            ng-model="model.partition_desc.partition_date_start" ng-if="state.mode=='edit'"
                            placeholder="Click to choose start date..." is-open="opened" />
+                    <small class="help-block" ng-show="model.partition_desc.partition_date_column!=null&& model.partition_desc.partition_date_start==null">Please input start date when partition date column selected.</small>
                   <!--vier model will convert use filter-->
                     <span ng-if="state.mode=='view'&&model.partition_desc.partition_date_column">{{(model.partition_desc.partition_date_start)|reverseToGMT0 }}</span>
                 </div>
@@ -131,7 +134,6 @@
                         <ol class="text-info">
                             <li>Not required,leave as default if cube always need full build</li>
                             <li>Partition column will select 'date' or 'string' type column from fact table</li>
-                            <li>If column selected,please indicate start date to just pull certain data from source</li>
                         </ol>
                     </div>
                 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/partials/modelDesigner/data_model.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/data_model.html b/webapp/app/partials/modelDesigner/data_model.html
index 79c6533..5f31201 100644
--- a/webapp/app/partials/modelDesigner/data_model.html
+++ b/webapp/app/partials/modelDesigner/data_model.html
@@ -25,11 +25,10 @@
             <label class="col-xs-12 col-sm-2 concube.detailtrol-label no-padding-right font-color-default">
                 <b>Fact Table</b>
             </label>
-            <div class="col-xs-12 col-sm-6" ng-class="forms.data_model_form.innerform.typeahead.$invalid?'has-error':''">
+            <div class="col-xs-12 col-sm-6" ng-class="{'has-error':forms.data_model_form.innerform.typeahead.$invalid && (forms.data_model_form.innerform.typeahead.$dirty||forms.data_model_form.$sbumitted)}">
                 <typeahead ng-if="state.mode=='edit'" items="tableModel.selectProjectTables" prompt="Fact Table Name"
                            title="name" model="model.fact_table" required="true"></typeahead>
-                <small class="help-block" ng-show="forms.data_model_form.innerform.typeahead.$error.required">The fact table is required</small>
-
+                <small class="help-block" ng-show="forms.data_model_form.innerform.typeahead.$error.required && (forms.data_model_form.innerform.typeahead.$dirty||forms.data_model_form.$sbumitted)">The fact table is required</small>
                 <span ng-if="state.mode=='view'">{{model.fact_table}}</span>
             </div>
         </div>
@@ -111,13 +110,15 @@
                 <div class="col-xs-8">
                     <ng-form name="lookup_form">
                     <!--Table Name-->
-                    <div class="form-group" ng-class="lookup_form.innerform.typeahead.$invalid?'has-error':''">
+                    <div class="form-group">
                         <div class="row">
                             <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Lookup Table Name</b></label>
-                            <div class="col-xs-12 col-sm-6">
-                                <typeahead items="tableModel.selectProjectTables" prompt="Lookup Table Name" required="true" title="name" model="newLookup.table"></typeahead>
+                            <div ng-class="{'has-error':lookup_form.innerform.typeahead.$invalid && (lookup_form.innerform.typeahead.$dirty||forms.model_info_form.$sbumitted)}">
+                                <div class="col-xs-12 col-sm-6">
+                                    <typeahead items="tableModel.selectProjectTables" prompt="Lookup Table Name" required="true" title="name" model="newLookup.table"></typeahead>
+                                    <small class="help-block" ng-show="lookup_form.innerform.typeahead.$invalid && (lookup_form.innerform.typeahead.$dirty||forms.model_info_form.$sbumitted)">Table name required</small>
+                                </div>
                             </div>
-                            <small class="help-block" ng-show="lookup_form.innerform.typeahead.$error.required">Table name required</small>
                         </div>
                     </div>
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/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 095203d..e7fe07e 100644
--- a/webapp/app/partials/modelDesigner/model_dimensions.html
+++ b/webapp/app/partials/modelDesigner/model_dimensions.html
@@ -18,6 +18,7 @@
 
 <div ng-controller="ModelDimensionsCtrl">
 
+   <ng-form name="forms.model_dimensions_form" novalidate>
     <!-- Dimensions Summary -->
     <div class="dataTables_wrapper form-inline no-footer">
         <div class="row"  ng-if="state.mode=='view'&&model.dimensions.length > 0">
@@ -32,8 +33,8 @@
             </div>
         </div>
 
-        <ng-form name="forms.model_dimensions_form" novalidate>
          <!-- VIEW MODE -->
+        <div class="row">
             <table class="table table-striped table-hover" ng-if="state.mode=='view'&&model.dimensions.length > 0">
                 <thead>
                     <tr>
@@ -53,13 +54,13 @@
                             <span>{{dimension.table}}</span>
                         </td>
                         <!--Table Name -->
-                        <td>
+                        <td class="tb-breakword">
                             <span>{{dimension.columns}}</span>
                         </td>
                     </tr>
                 </tbody>
             </table>
-        </ng-form>
+        </div>
         <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%"
@@ -82,7 +83,7 @@
                     <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-model="model.dimensions[$index].columns" chosen multiple
                                 ng-change=""
                                 ng-options="column.name as column.name for column in getColumnsByTable(dimension.table)">
                             <option value=""></option>
@@ -93,4 +94,5 @@
          </div>
 
     </div>
-</div>
\ No newline at end of file
+   </ng-form>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/partials/modelDesigner/model_info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/model_info.html b/webapp/app/partials/modelDesigner/model_info.html
index 21a8185..097739c 100644
--- a/webapp/app/partials/modelDesigner/model_info.html
+++ b/webapp/app/partials/modelDesigner/model_info.html
@@ -20,27 +20,6 @@
     <div class="col-xs-8">
         <!--Project-->
         <ng-form name="forms.model_info_form" novalidate>
-            <div class="form-group">
-                <div class="row">
-                    <label class="col-xs-3 control-label no-padding-right">
-                        <a ng-if="state.mode=='edit'" href="projects">
-                            <b>Project</b>
-                        </a>
-                        <b ng-if="state.mode=='view'" class="font-color-default">Project</b>
-                    </label>
-                    <div class="col-xs-6" ng-class="forms.model_info_form.project_name.$invalid?'has-error':''">
-                         <!--edit-->
-                        <input ng-if="state.mode=='edit'" required name="project_name" type="text" class="form-control"
-                               ng-model="model.project"/>
-                        <small class="help-block" ng-show="forms.model_info_form.project_name.$error.required">The project is required</small>
-
-                        <!--view-->
-                        <span ng-if="state.mode=='view'">
-                            {{model.project}}
-                        </span>
-                    </div>
-                </div>
-            </div>
 
             <!--Model Name-->
             <div class="form-group">
@@ -49,15 +28,15 @@
                         <b>Model Name</b>
                     </label>
 
-                    <div class="col-xs-12 col-sm-6" ng-class="forms.model_info_form.model_name.$invalid?'has-error':''">
+                    <div class="col-xs-12 col-sm-6" ng-class="{'has-error':forms.model_info_form.model_name.$invalid && (forms.model_info_form.model_name.$dirty||forms.model_info_form.$sbumitted)}">
 
                         <!-- edit -->
                         <input ng-if="state.mode=='edit'" name="model_name" type="text" class="form-control"
                                ng-model="model.name" required
                                placeholder="You can use letters, numbers, and '_'"
                                ng-maxlength=100 ng-pattern="/^\w+$/" />
-                        <small class="help-block" ng-show="forms.model_info_form.model_name.$error.required  && forms.model_info_form.model_name.$dirty">Model name is required.</small>
-                        <small class="help-block" ng-show="forms.model_info_form.model_name.$invalid && forms.model_info_form.model_name.$dirty && !forms.model_info_form.model_name.$error.required"> Model name is invalid.</small>
+                        <small class="help-block" ng-show="forms.model_info_form.model_name.$error.required && (forms.model_info_form.model_name.$dirty||forms.model_info_form.$sbumitted)">Model name is required.</small>
+                        <small class="help-block" ng-show="!forms.model_info_form.model_name.$error.required&&forms.model_info_form.model_name.$invalid && (forms.model_info_form.model_name.$dirty||forms.model_info_form.$sbumitted)">Model name is invalid.</small>
 
 
                         <span ng-if="state.mode=='view'">{{model.name}}</span>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/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 2f58bed..b2cf20c 100644
--- a/webapp/app/partials/models/model_schema.html
+++ b/webapp/app/partials/models/model_schema.html
@@ -14,7 +14,7 @@
 * 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.
--->
+-->A
 
 <!--hide when view model and no model selected-->
 <div class="box box-primary model-design box-2px" ng-hide="state.mode=='view'&&!model.name">
@@ -46,16 +46,16 @@
                         </div>
                     </div>
                     <div class="col-xs-4 pull-right">
-                        <button class="btn btn-prev" ng-click="checkForm()?preView():''" ng-show="curStep.title!='Model Info'">
+                        <button class="btn btn-prev" ng-click="preView()" ng-show="curStep.title!='Model Info'">
                             <i class="ace-icon fa fa-arrow-left"></i>
                             Prev
                         </button>
-                        <button id="nextButton" class="btn btn-success btn-next"  ng-click="checkForm()?nextView():''"
+                        <button id="nextButton" class="btn btn-success btn-next" ng-disabled="forms[curStep.form].$invalid" 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()"
+                        <button class="btn btn-primary" ng-click="saveModel()"
                                 ng-if="curStep.title=='Settings' && state.mode=='edit'">
                             Save
                         </button>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/aebd109e/webapp/app/partials/projects/project_table_tree.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/projects/project_table_tree.html b/webapp/app/partials/projects/project_table_tree.html
index 3ee6d5b..b0c1e53 100644
--- a/webapp/app/partials/projects/project_table_tree.html
+++ b/webapp/app/partials/projects/project_table_tree.html
@@ -24,7 +24,7 @@
     </div>
     <div class="space-4"></div>
     <div style="width:310px; height:800px; overflow:auto">
-        <abn-tree ng-if="selectedSrcDb.length > 0"
+        <abn-tree
                 tree-data         = "selectedSrcDb"
                 tree-control      = "my_tree"
                 icon-leaf         = "fa fa-columns"