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:21:58 UTC

[29/52] [abbrv] incubator-kylin git commit: new model list page update

new model list page update


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

Branch: refs/heads/0.8.0
Commit: b998dbc3609fe1a19feb4e46a3f33f82920b863b
Parents: 16b6664
Author: jiazhong <ji...@ebay.com>
Authored: Tue Mar 24 16:15:12 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:52 2015 +0800

----------------------------------------------------------------------
 webapp/app/index.html                           |   2 +-
 webapp/app/js/controllers/cubeAdvanceSetting.js |   2 +-
 webapp/app/js/controllers/cubeDimensions.js     |   5 +-
 webapp/app/js/controllers/cubeEdit.js           |  77 ++-
 webapp/app/js/controllers/cubeFilter.js         |   2 +-
 webapp/app/js/controllers/cubeModel.js          |   2 +-
 webapp/app/js/controllers/cubeRefresh.js        |   2 +-
 webapp/app/js/controllers/cubeSchema.js         |   7 +-
 webapp/app/js/controllers/cubes.js              |   7 +-
 webapp/app/js/controllers/models.js             |  30 +-
 .../js/directives/kylin_abn_tree_directive.js   | 492 +++++++++++++++++++
 webapp/app/js/model/cubeDescModel.js            |   1 +
 webapp/app/js/model/modelList.js                |  24 +-
 webapp/app/less/component.less                  |  12 +
 .../app/partials/cubeDesigner/dimensions.html   |   6 +-
 webapp/app/partials/cubeDesigner/info.html      |   9 +-
 webapp/app/partials/cubeDesigner/measures.html  |   2 +-
 webapp/app/partials/cubeDesigner/overview.html  |   6 +-
 webapp/app/partials/models/_models.html         | 117 -----
 webapp/app/partials/models/model_schema.html    |  16 +-
 webapp/app/partials/models/models.html          |  36 +-
 webapp/app/partials/models/models_info.html     |  46 --
 webapp/app/partials/models/models_tree.html     |   6 +-
 webapp/app/partials/tables/table_detail.html    |   2 +-
 webapp/app/routes.json                          |  14 +-
 webapp/grunt.json                               |   1 +
 26 files changed, 678 insertions(+), 248 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/index.html
----------------------------------------------------------------------
diff --git a/webapp/app/index.html b/webapp/app/index.html
index ac5c7b7..8901721 100644
--- a/webapp/app/index.html
+++ b/webapp/app/index.html
@@ -102,13 +102,13 @@
 <script src="components/angular-underscore/angular-underscore.js"></script>
 <script src="components/jquery-ui/jquery-ui.min.js"></script>
 <script src="components/angular-ui-sortable/sortable.min.js"></script>
-<script src="components/angular-bootstrap-nav-tree/dist/abn_tree_directive.js"></script>
 
 <script src="js/app.js"></script>
 <script src="js/config.js"></script>
 <script src="js/listeners.js"></script>
 <script src="js/filters/filter.js"></script>
 <script src="js/directives/directives.js"></script>
+<script src="js/directives/kylin_abn_tree_directive.js"></script>
 <script src="js/factories/graph.js"></script>
 <script src="js/services/cache.js"></script>
 <script src="js/services/message.js"></script>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/controllers/cubeAdvanceSetting.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeAdvanceSetting.js b/webapp/app/js/controllers/cubeAdvanceSetting.js
index f1bd991..c9558d8 100644
--- a/webapp/app/js/controllers/cubeAdvanceSetting.js
+++ b/webapp/app/js/controllers/cubeAdvanceSetting.js
@@ -18,7 +18,7 @@
 
 'use strict';
 
-KylinApp.controller('CubeAdvanceSettingCtrl', function ($scope, $modal,cubeConfig,ModelService,MetaModel) {
+KylinApp.controller('CubeAdvanceSettingCtrl', function ($scope, $modal,cubeConfig,MetaModel) {
 
     //convert some undefined or null value
     angular.forEach($scope.cubeMetaFrame.rowkey.rowkey_columns,function(rowkey){

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/controllers/cubeDimensions.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeDimensions.js b/webapp/app/js/controllers/cubeDimensions.js
index f323d1f..b24e9cc 100644
--- a/webapp/app/js/controllers/cubeDimensions.js
+++ b/webapp/app/js/controllers/cubeDimensions.js
@@ -63,7 +63,8 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel) {
         var factTable = $scope.metaModel.model.fact_table;
 
         // At first dump the columns of fact table.
-        var cols = $scope.getColumnsByTable(factTable);
+//        var cols = $scope.getColumnsByTable(factTable);
+        var cols = $scope.getDimColumnsByTable(factTable);
 
         // Initialize selected available.
         var factAvailable = {};
@@ -87,7 +88,7 @@ KylinApp.controller('CubeDimensionsCtrl', function ($scope, $modal,MetaModel) {
         var lookups = $scope.metaModel.model.lookups;
 
         for (var j = 0; j < lookups.length; j++) {
-            var cols2 = $scope.getColumnsByTable(lookups[j].table);
+            var cols2 = $scope.getDimColumnsByTable(lookups[j].table);
 
             // Initialize selected available.
             var lookupAvailable = {};

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/controllers/cubeEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeEdit.js b/webapp/app/js/controllers/cubeEdit.js
index fe099fd..01e1623 100755
--- a/webapp/app/js/controllers/cubeEdit.js
+++ b/webapp/app/js/controllers/cubeEdit.js
@@ -19,8 +19,12 @@
 'use strict';
 
 
-KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $location, $templateCache, $interpolate, MessageService, TableService, CubeDescService, CubeService, loadingRequest, SweetAlert,$log,cubeConfig,CubeDescModel,ModelService,MetaModel,TableModel) {
+KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $location, $templateCache, $interpolate, MessageService, TableService, CubeDescService, CubeService, loadingRequest, SweetAlert,$log,cubeConfig,CubeDescModel,MetaModel,TableModel,ModelDescService) {
     $scope.cubeConfig = cubeConfig;
+
+    $log.info("model name:"+$routeParams.modelName);
+    var modelName = $routeParams.modelName;
+
     //add or edit ?
     var absUrl = $location.absUrl();
     $scope.cubeMode = absUrl.indexOf("/cubes/add")!=-1?'addNewCube':absUrl.indexOf("/cubes/edit")!=-1?'editExistCube':'default';
@@ -36,6 +40,31 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         return temp;
     };
 
+    $scope.getDimColumnsByTable = function (tableName) {
+        if(!tableName){
+            return [];
+        }
+        var tableColumns = $scope.getColumnsByTable(tableName);
+        var tableDim = _.find($scope.metaModel.model.dimensions,function(dimension){return dimension.table == tableName});
+        var tableDimColumns = tableDim.columns;
+        var avaColObject = _.filter(tableColumns,function(col){
+            return tableDimColumns.indexOf(col.name)!=-1;
+        });
+        return avaColObject;
+    };
+
+    $scope.getMetricColumnsByTable = function (tableName) {
+        if(!tableName){
+            return [];
+        }
+        var tableColumns = $scope.getColumnsByTable(tableName);
+        var tableMetrics = $scope.metaModel.model.metrics;
+        var avaColObject = _.filter(tableColumns,function(col){
+            return tableMetrics.indexOf(col.name)!=-1;
+        });
+        return avaColObject;
+    };
+
     $scope.getPartitonColumns = function(tableName){
         var columns = _.filter($scope.getColumnsByTable(tableName),function(column){
             return column.datatype==="date"||column.datatype==="string";
@@ -85,32 +114,32 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         CubeDescService.get({cube_name: $routeParams.cubeName}, function (detail) {
             if (detail.length > 0) {
                 $scope.cubeMetaFrame = detail[0];
-                ModelService.get({model_name: $scope.cubeMetaFrame.model_name}, function (model) {
-                    if (model) {
-                        MetaModel.setMetaModel(model);
-                        $scope.metaModel = MetaModel;
-
-                        //use
-                        //convert GMT mills ,to make sure partition date show GMT Date
-                        //should run only one time
-                        if(model.partition_desc&&model.partition_desc.partition_date_start)
-                        {
-                            MetaModel.converDateToGMT();
-                        }
-                    }
-                });
                 $scope.state.cubeSchema = angular.toJson($scope.cubeMetaFrame, true);
             }
         });
 
     } else {
         $scope.cubeMetaFrame = CubeDescModel.createNew();
-        MetaModel.initModel();
-        $scope.metaModel = MetaModel;
-        $scope.cubeMetaFrame.project = $scope.projectModel.selectedProject;
+//        MetaModel.initModel();
+//        $scope.metaModel = MetaModel;
+        $scope.cubeMetaFrame.model_name = modelName;
         $scope.state.cubeSchema = angular.toJson($scope.cubeMetaFrame, true);
     }
 
+    ModelDescService.get({model_name: $scope.cubeMetaFrame.model_name}, function (model) {
+        if (model) {
+            MetaModel.setMetaModel(model);
+            $scope.metaModel = MetaModel;
+            //use
+            //convert GMT mills ,to make sure partition date show GMT Date
+            //should run only one time
+            if(model.partition_desc&&model.partition_desc.partition_date_start)
+            {
+                MetaModel.converDateToGMT();
+            }
+        }
+    });
+
     // ~ public methods
     $scope.aceChanged = function () {
     };
@@ -149,7 +178,6 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
 //        delete $scope.cubeMetaFrame.project;
 
         $scope.state.cubeSchema = angular.toJson($scope.cubeMetaFrame, true);
-        $scope.state.modelSchema = angular.toJson($scope.metaModel.model, true);
     };
 
     $scope.cubeResultTmpl = function (notification) {
@@ -180,7 +208,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
                 loadingRequest.show();
 
                 if ($scope.isEdit) {
-                    CubeService.update({}, {cubeDescData: $scope.state.cubeSchema,modelDescData:$scope.state.modelSchema, cubeName: $routeParams.cubeName, project: $scope.state.project}, function (request) {
+                    CubeService.update({}, {cubeDescData: $scope.state.cubeSchema, cubeName: $routeParams.cubeName, project: $scope.state.project}, function (request) {
                         if (request.successful) {
                             $scope.state.cubeSchema = request.cubeDescData;
                             MessageService.sendMsg($scope.cubeResultTmpl({'text':'Updated the cube successfully.',type:'success'}), 'success', {}, true, 'top_center');
@@ -210,7 +238,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
                         loadingRequest.hide();
                     });
                 } else {
-                    CubeService.save({}, {cubeDescData: $scope.state.cubeSchema,modelDescData:$scope.state.modelSchema, project: $scope.state.project}, function (request) {
+                    CubeService.save({}, {cubeDescData: $scope.state.cubeSchema, project: $scope.state.project}, function (request) {
                         if(request.successful) {
                             $scope.state.cubeSchema = request.cubeDescData;
 
@@ -357,7 +385,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         //! here get the latest rowkey_columns
         $scope.cubeMetaFrame.rowkey.rowkey_columns = newRowKeyColumns;
 
-        if($scope.modelMode==="editExistCube") {
+        if($scope.cubeMode==="editExistCube") {
             var aggregationGroups = $scope.cubeMetaFrame.rowkey.aggregation_groups;
             // rm unused item from group,will only rm when [edit] dimension
             angular.forEach(aggregationGroups, function (group, index) {
@@ -387,7 +415,7 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
             });
         }
 
-        if($scope.modelMode==="addNewCube"){
+        if($scope.cubeMode==="addNewCube"){
 
           if(!tmpAggregationItems.length) {
               $scope.cubeMetaFrame.rowkey.aggregation_groups=[];
@@ -528,9 +556,6 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
             }
             groups[j].push(groupItems[i]);
         }
-//        if(groups[groups.length-1].length<10){
-//            groups.pop();
-//        }
         return groups;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/controllers/cubeFilter.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeFilter.js b/webapp/app/js/controllers/cubeFilter.js
index 3c38f1d..3953169 100644
--- a/webapp/app/js/controllers/cubeFilter.js
+++ b/webapp/app/js/controllers/cubeFilter.js
@@ -18,6 +18,6 @@
 
 'use strict';
 
-KylinApp.controller('CubeFilterCtrl', function ($scope, $modal,cubeConfig,ModelService,MetaModel) {
+KylinApp.controller('CubeFilterCtrl', function ($scope, $modal,cubeConfig,MetaModel) {
 
 });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/controllers/cubeModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeModel.js b/webapp/app/js/controllers/cubeModel.js
index cfe0f1c..47014c9 100644
--- a/webapp/app/js/controllers/cubeModel.js
+++ b/webapp/app/js/controllers/cubeModel.js
@@ -18,7 +18,7 @@
 
 'use strict';
 
-KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,ModelService,MetaModel,SweetAlert,GraphService,$log) {
+KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,MetaModel,SweetAlert,GraphService,$log) {
 
     //copy model for show Json in model tab list
     $scope.modelJson = angular.copy($scope.model);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/controllers/cubeRefresh.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeRefresh.js b/webapp/app/js/controllers/cubeRefresh.js
index 640f2c8..39a63c7 100644
--- a/webapp/app/js/controllers/cubeRefresh.js
+++ b/webapp/app/js/controllers/cubeRefresh.js
@@ -18,6 +18,6 @@
 
 'use strict';
 
-KylinApp.controller('CubeRefreshCtrl', function ($scope, $modal,cubeConfig,ModelService,MetaModel) {
+KylinApp.controller('CubeRefreshCtrl', function ($scope, $modal,cubeConfig,MetaModel) {
 
 });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/controllers/cubeSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeSchema.js b/webapp/app/js/controllers/cubeSchema.js
index d883b59..69bb25e 100755
--- a/webapp/app/js/controllers/cubeSchema.js
+++ b/webapp/app/js/controllers/cubeSchema.js
@@ -18,7 +18,7 @@
 
 'use strict';
 
-KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserService, ProjectService, AuthenticationService,$filter,ModelService,MetaModel,CubeDescModel,CubeList,TableModel,ProjectModel) {
+KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserService, ProjectService, AuthenticationService,$filter,ModelService,MetaModel,CubeDescModel,CubeList,TableModel,ProjectModel,ModelDescService) {
 
     $scope.projects = [];
     $scope.newDimension = null;
@@ -27,11 +27,8 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
 
     $scope.wizardSteps = [
         {title: 'Cube Info', src: 'partials/cubeDesigner/info.html', isComplete: false},
-        {title: 'Data Model', src: 'partials/cubeDesigner/data_model.html', isComplete: false},
         {title: 'Dimensions', src: 'partials/cubeDesigner/dimensions.html', isComplete: false},
         {title: 'Measures', src: 'partials/cubeDesigner/measures.html', isComplete: false},
-        {title: 'Filter', src: 'partials/cubeDesigner/filter.html', isComplete: false},
-        {title: 'Refresh Setting', src: 'partials/cubeDesigner/incremental.html', isComplete: false}
     ];
     if (UserService.hasRole("ROLE_ADMIN")) {
             $scope.wizardSteps.push({title: 'Advanced Setting', src: 'partials/cubeDesigner/advanced_settings.html', isComplete: false});
@@ -59,7 +56,7 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
             }
 
             //init model
-            ModelService.get({model_name: $scope.cubeMetaFrame.model_name}, function (model) {
+            ModelDescService.get({model_name: $scope.cubeMetaFrame.model_name}, function (model) {
                 if (model) {
                     $scope.metaModel.model = model;
                 }

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/controllers/cubes.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubes.js b/webapp/app/js/controllers/cubes.js
index fce706a..94c6031 100755
--- a/webapp/app/js/controllers/cubes.js
+++ b/webapp/app/js/controllers/cubes.js
@@ -19,7 +19,7 @@
 'use strict';
 
 KylinApp
-    .controller('CubesCtrl', function ($scope, $q, $routeParams, $location, $modal, MessageService, CubeDescService, CubeService, JobService, UserService,  ProjectService,SweetAlert,loadingRequest,$log,cubeConfig,ProjectModel,ModelService,MetaModel,CubeList) {
+    .controller('CubesCtrl', function ($scope, $q, $routeParams, $location, $modal, MessageService, CubeDescService, CubeService, JobService, UserService,  ProjectService,SweetAlert,loadingRequest,$log,cubeConfig,ProjectModel,ModelService,MetaModel,CubeList,ModelDescService) {
 
         $scope.cubeConfig = cubeConfig;
         $scope.cubeList = CubeList;
@@ -84,8 +84,9 @@ KylinApp
                 CubeDescService.get({cube_name: cube.name}, {}, function (detail) {
                     if (detail.length > 0&&detail[0].hasOwnProperty("name")) {
                         cube.detail = detail[0];
-                        ModelService.get({model_name: cube.detail.model_name}, function (model) {
-                          cube.model = model
+                        ModelDescService.get({model_name: cube.detail.model_name}, function (model) {
+                          cube.model = model;
+                          $scope.metaModel.model= model;
                           defer.resolve(cube.detail);
                        });
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/controllers/models.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/models.js b/webapp/app/js/controllers/models.js
index 9f93ab6..f40e8ec 100644
--- a/webapp/app/js/controllers/models.js
+++ b/webapp/app/js/controllers/models.js
@@ -23,12 +23,13 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
         $scope.model = {};
         //tree data
         $scope.models_treedata=[];
+        $scope.selectedCubes = [];
 
         $scope.showModels=true;
 
         $scope.toggleTab = function(showModel){
             $scope.showModels = showModel;
-//            console.log($scope.showModels);
+            console.log($scope.showModels);
         }
 
         $scope.modelList = ModelList;
@@ -82,11 +83,21 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
                         onSelect:function(branch){
                          // set selecte model
                             $scope.model=branch.data;
+                            $scope.selectedCubes = branch.data.cubes;
                         }
                     };
                     var _children = [];
                     angular.forEach(model.cubes,function(cube){
-                        _children.push(cube.name);
+                        _children.push(
+                            {
+                                label:cube.name,
+                                data:cube,
+                                onSelect:function(branch){
+                                    console.log("cube selected:"+branch.data);
+                                    // set selecte model
+                                }
+                            }
+                        );
                     });
                     if(_children.length){
                          _model.children = _children;
@@ -105,4 +116,19 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
                 $scope.init();
         });
 
+    $scope.status = {
+        isopen: true
+    };
+
+    $scope.toggled = function(open) {
+        $log.log('Dropdown is now: ', open);
+    };
+
+    $scope.toggleDropdown = function($event) {
+        $event.preventDefault();
+        $event.stopPropagation();
+        $scope.status.isopen = !$scope.status.isopen;
+    };
+
+
     });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/directives/kylin_abn_tree_directive.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/directives/kylin_abn_tree_directive.js b/webapp/app/js/directives/kylin_abn_tree_directive.js
new file mode 100644
index 0000000..f309995
--- /dev/null
+++ b/webapp/app/js/directives/kylin_abn_tree_directive.js
@@ -0,0 +1,492 @@
+(function() {
+  var module,
+    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+  module = angular.module('angularBootstrapNavTree', []);
+
+  module.directive('abnTree', [
+    '$timeout', function($timeout) {
+      return {
+        restrict: 'E',
+        template: "<ul class=\"nav nav-list nav-pills nav-stacked abn-tree\">\n  <li ng-repeat=\"row in tree_rows | filter:{visible:true} track by row.branch.uid\" ng-animate=\"'abn-tree-animate'\" ng-class=\"'level-' + {{ row.level }} + (row.branch.selected ? ' active':'') + ' ' +row.classes.join(' ')\" class=\"abn-tree-row\"><a ng-click=\"user_clicks_branch(row.branch)\"><i ng-class=\"row.tree_icon\" ng-click=\"row.branch.expanded = !row.branch.expanded\" class=\"indented tree-icon\"> </i><span class=\"indented tree-label\">{{ row.label }} </span></a></li>\n</ul>",
+        replace: true,
+        scope: {
+          treeData: '=',
+          onSelect: '&',
+          initialSelection: '@',
+          treeControl: '='
+        },
+        link: function(scope, element, attrs) {
+          var error, expand_all_parents, expand_level, for_all_ancestors, for_each_branch, get_parent, n, on_treeData_change, select_branch, selected_branch, tree;
+          error = function(s) {
+            console.log('ERROR:' + s);
+            debugger;
+            return void 0;
+          };
+          if (attrs.iconExpand == null) {
+            attrs.iconExpand = 'icon-plus  glyphicon glyphicon-plus  fa fa-plus';
+          }
+          if (attrs.iconCollapse == null) {
+            attrs.iconCollapse = 'icon-minus glyphicon glyphicon-minus fa fa-minus';
+          }
+          if (attrs.iconLeaf == null) {
+            attrs.iconLeaf = 'icon-file  glyphicon glyphicon-file  fa fa-file';
+          }
+          if (attrs.expandLevel == null) {
+            attrs.expandLevel = '3';
+          }
+          expand_level = parseInt(attrs.expandLevel, 10);
+          if (!scope.treeData) {
+            alert('no treeData defined for the tree!');
+            return;
+          }
+          if (scope.treeData.length == null) {
+            if (treeData.label != null) {
+              scope.treeData = [treeData];
+            } else {
+              alert('treeData should be an array of root branches');
+              return;
+            }
+          }
+          for_each_branch = function(f) {
+            var do_f, root_branch, _i, _len, _ref, _results;
+            do_f = function(branch, level) {
+              var child, _i, _len, _ref, _results;
+              f(branch, level);
+              if (branch.children != null) {
+                _ref = branch.children;
+                _results = [];
+                for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+                  child = _ref[_i];
+                  _results.push(do_f(child, level + 1));
+                }
+                return _results;
+              }
+            };
+            _ref = scope.treeData;
+            _results = [];
+            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+              root_branch = _ref[_i];
+              _results.push(do_f(root_branch, 1));
+            }
+            return _results;
+          };
+          selected_branch = null;
+          select_branch = function(branch) {
+            if (!branch) {
+              if (selected_branch != null) {
+                selected_branch.selected = false;
+              }
+              selected_branch = null;
+              return;
+            }
+            if (branch !== selected_branch) {
+              if (selected_branch != null) {
+                selected_branch.selected = false;
+              }
+              branch.selected = true;
+              selected_branch = branch;
+              expand_all_parents(branch);
+              if (branch.onSelect != null) {
+                return $timeout(function() {
+                  return branch.onSelect(branch);
+                });
+              } else {
+                if (scope.onSelect != null) {
+                  return $timeout(function() {
+                    return scope.onSelect({
+                      branch: branch
+                    });
+                  });
+                }
+              }
+            }
+          };
+          scope.user_clicks_branch = function(branch) {
+            if (branch !== selected_branch) {
+              return select_branch(branch);
+            }
+          };
+          get_parent = function(child) {
+            var parent;
+            parent = void 0;
+            if (child.parent_uid) {
+              for_each_branch(function(b) {
+                if (b.uid === child.parent_uid) {
+                  return parent = b;
+                }
+              });
+            }
+            return parent;
+          };
+          for_all_ancestors = function(child, fn) {
+            var parent;
+            parent = get_parent(child);
+            if (parent != null) {
+              fn(parent);
+              return for_all_ancestors(parent, fn);
+            }
+          };
+          expand_all_parents = function(child) {
+            return for_all_ancestors(child, function(b) {
+              return b.expanded = true;
+            });
+          };
+          scope.tree_rows = [];
+          on_treeData_change = function() {
+            var add_branch_to_list, root_branch, _i, _len, _ref, _results;
+            for_each_branch(function(b, level) {
+              if (!b.uid) {
+                return b.uid = "" + Math.random();
+              }
+            });
+            console.log('UIDs are set.');
+            for_each_branch(function(b) {
+              var child, _i, _len, _ref, _results;
+              if (angular.isArray(b.children)) {
+                _ref = b.children;
+                _results = [];
+                for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+                  child = _ref[_i];
+                  _results.push(child.parent_uid = b.uid);
+                }
+                return _results;
+              }
+            });
+            scope.tree_rows = [];
+            for_each_branch(function(branch) {
+              var child, f;
+              if (branch.children) {
+                if (branch.children.length > 0) {
+                  f = function(e) {
+                    if (typeof e === 'string') {
+                      return {
+                        label: e,
+                        children: []
+                      };
+                    } else {
+                      return e;
+                    }
+                  };
+                  return branch.children = (function() {
+                    var _i, _len, _ref, _results;
+                    _ref = branch.children;
+                    _results = [];
+                    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+                      child = _ref[_i];
+                      _results.push(f(child));
+                    }
+                    return _results;
+                  })();
+                }
+              } else {
+                return branch.children = [];
+              }
+            });
+            add_branch_to_list = function(level, branch, visible) {
+              var child, child_visible, tree_icon, _i, _len, _ref, _results;
+              if (branch.expanded == null) {
+                branch.expanded = false;
+              }
+              if (branch.classes == null) {
+                branch.classes = [];
+              }
+              if (!branch.noLeaf && (!branch.children || branch.children.length === 0)) {
+                tree_icon = attrs.iconLeaf;
+                if (__indexOf.call(branch.classes, "leaf") < 0) {
+                  branch.classes.push("leaf");
+                }
+              } else {
+                if (branch.expanded) {
+                  tree_icon = attrs.iconCollapse;
+                } else {
+                  tree_icon = attrs.iconExpand;
+                }
+              }
+              scope.tree_rows.push({
+                level: level,
+                branch: branch,
+                label: branch.label,
+                classes: branch.classes,
+                tree_icon: tree_icon,
+                visible: visible
+              });
+              if (branch.children != null) {
+                _ref = branch.children;
+                _results = [];
+                for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+                  child = _ref[_i];
+                  child_visible = visible && branch.expanded;
+                  _results.push(add_branch_to_list(level + 1, child, child_visible));
+                }
+                return _results;
+              }
+            };
+            _ref = scope.treeData;
+            _results = [];
+            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+              root_branch = _ref[_i];
+              _results.push(add_branch_to_list(1, root_branch, true));
+            }
+            return _results;
+          };
+          scope.$watch('treeData', on_treeData_change, true);
+          if (attrs.initialSelection != null) {
+            for_each_branch(function(b) {
+              if (b.label === attrs.initialSelection) {
+                return $timeout(function() {
+                  return select_branch(b);
+                });
+              }
+            });
+          }
+          n = scope.treeData.length;
+          console.log('num root branches = ' + n);
+          for_each_branch(function(b, level) {
+            b.level = level;
+            return b.expanded = b.level < expand_level;
+          });
+          if (scope.treeControl != null) {
+            if (angular.isObject(scope.treeControl)) {
+              tree = scope.treeControl;
+              tree.expand_all = function() {
+                return for_each_branch(function(b, level) {
+                  return b.expanded = true;
+                });
+              };
+              tree.collapse_all = function() {
+                return for_each_branch(function(b, level) {
+                  return b.expanded = false;
+                });
+              };
+              tree.get_first_branch = function() {
+                n = scope.treeData.length;
+                if (n > 0) {
+                  return scope.treeData[0];
+                }
+              };
+              tree.select_first_branch = function() {
+                var b;
+                b = tree.get_first_branch();
+                return tree.select_branch(b);
+              };
+              tree.get_selected_branch = function() {
+                return selected_branch;
+              };
+              tree.get_parent_branch = function(b) {
+                return get_parent(b);
+              };
+              tree.select_branch = function(b) {
+                select_branch(b);
+                return b;
+              };
+              tree.get_children = function(b) {
+                return b.children;
+              };
+              tree.select_parent_branch = function(b) {
+                var p;
+                if (b == null) {
+                  b = tree.get_selected_branch();
+                }
+                if (b != null) {
+                  p = tree.get_parent_branch(b);
+                  if (p != null) {
+                    tree.select_branch(p);
+                    return p;
+                  }
+                }
+              };
+              tree.add_branch = function(parent, new_branch) {
+                if (parent != null) {
+                  parent.children.push(new_branch);
+                  parent.expanded = true;
+                } else {
+                  scope.treeData.push(new_branch);
+                }
+                return new_branch;
+              };
+              tree.add_root_branch = function(new_branch) {
+                tree.add_branch(null, new_branch);
+                return new_branch;
+              };
+              tree.expand_branch = function(b) {
+                if (b == null) {
+                  b = tree.get_selected_branch();
+                }
+                if (b != null) {
+                  b.expanded = true;
+                  return b;
+                }
+              };
+              tree.collapse_branch = function(b) {
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  b.expanded = false;
+                  return b;
+                }
+              };
+              tree.get_siblings = function(b) {
+                var p, siblings;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  p = tree.get_parent_branch(b);
+                  if (p) {
+                    siblings = p.children;
+                  } else {
+                    siblings = scope.treeData;
+                  }
+                  return siblings;
+                }
+              };
+              tree.get_next_sibling = function(b) {
+                var i, siblings;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  siblings = tree.get_siblings(b);
+                  n = siblings.length;
+                  i = siblings.indexOf(b);
+                  if (i < n) {
+                    return siblings[i + 1];
+                  }
+                }
+              };
+              tree.get_prev_sibling = function(b) {
+                var i, siblings;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                siblings = tree.get_siblings(b);
+                n = siblings.length;
+                i = siblings.indexOf(b);
+                if (i > 0) {
+                  return siblings[i - 1];
+                }
+              };
+              tree.select_next_sibling = function(b) {
+                var next;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  next = tree.get_next_sibling(b);
+                  if (next != null) {
+                    return tree.select_branch(next);
+                  }
+                }
+              };
+              tree.select_prev_sibling = function(b) {
+                var prev;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  prev = tree.get_prev_sibling(b);
+                  if (prev != null) {
+                    return tree.select_branch(prev);
+                  }
+                }
+              };
+              tree.get_first_child = function(b) {
+                var _ref;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  if (((_ref = b.children) != null ? _ref.length : void 0) > 0) {
+                    return b.children[0];
+                  }
+                }
+              };
+              tree.get_closest_ancestor_next_sibling = function(b) {
+                var next, parent;
+                next = tree.get_next_sibling(b);
+                if (next != null) {
+                  return next;
+                } else {
+                  parent = tree.get_parent_branch(b);
+                  return tree.get_closest_ancestor_next_sibling(parent);
+                }
+              };
+              tree.get_next_branch = function(b) {
+                var next;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  next = tree.get_first_child(b);
+                  if (next != null) {
+                    return next;
+                  } else {
+                    next = tree.get_closest_ancestor_next_sibling(b);
+                    return next;
+                  }
+                }
+              };
+              tree.select_next_branch = function(b) {
+                var next;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  next = tree.get_next_branch(b);
+                  if (next != null) {
+                    tree.select_branch(next);
+                    return next;
+                  }
+                }
+              };
+              tree.last_descendant = function(b) {
+                var last_child;
+                if (b == null) {
+                  debugger;
+                }
+                n = b.children.length;
+                if (n === 0) {
+                  return b;
+                } else {
+                  last_child = b.children[n - 1];
+                  return tree.last_descendant(last_child);
+                }
+              };
+              tree.get_prev_branch = function(b) {
+                var parent, prev_sibling;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  prev_sibling = tree.get_prev_sibling(b);
+                  if (prev_sibling != null) {
+                    return tree.last_descendant(prev_sibling);
+                  } else {
+                    parent = tree.get_parent_branch(b);
+                    return parent;
+                  }
+                }
+              };
+              return tree.select_prev_branch = function(b) {
+                var prev;
+                if (b == null) {
+                  b = selected_branch;
+                }
+                if (b != null) {
+                  prev = tree.get_prev_branch(b);
+                  if (prev != null) {
+                    tree.select_branch(prev);
+                    return prev;
+                  }
+                }
+              };
+            }
+          }
+        }
+      };
+    }
+  ]);
+
+}).call(this);

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/model/cubeDescModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/cubeDescModel.js b/webapp/app/js/model/cubeDescModel.js
index 773ce95..ad87393 100644
--- a/webapp/app/js/model/cubeDescModel.js
+++ b/webapp/app/js/model/cubeDescModel.js
@@ -24,6 +24,7 @@ KylinApp.service('CubeDescModel',function(){
     this.createNew = function () {
             var cubeMeta = {
                 "name": "",
+                "model_name": "",
                 "description": "",
                 "dimensions": [],
                 "measures": [

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/js/model/modelList.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/modelList.js b/webapp/app/js/model/modelList.js
index 6d56a10..e5be622 100644
--- a/webapp/app/js/model/modelList.js
+++ b/webapp/app/js/model/modelList.js
@@ -23,21 +23,29 @@ KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService,
     this.list = function(queryParam){
 
         var defer = $q.defer();
+        var cubeDetail = [];
         ModelService.list(queryParam, function (_models) {
+
             angular.forEach(_models, function (model, index) {
                 AccessService.list({type: "DataModelDesc", uuid: model.uuid}, function (accessEntities) {
                     model.accessEntities = accessEntities;
                 });
 //                add cube info to model
-                CubeService.list({offset: 0, limit: 70,modelName:model.name}, function (_cubes) {
-                    model.cubes=_cubes;
-                });
+                cubeDetail.push(
+                    CubeService.list({offset: 0, limit: 70,modelName:model.name}, function (_cubes) {
+                    model.cubes = _cubes;
+                    }).$promise
+                );
 
-                model.project =ProjectModel.getProjectByCubeModel(model.name);
+                model.project = ProjectModel.getProjectByCubeModel(model.name);
             });
-            _models = _.filter(_models,function(models){return models.name!=undefined});
-            _this.models = _this.models.concat(_models);
-            defer.resolve(_this.models);
+            $q.all(cubeDetail).then(
+                function(result){
+                    _models = _.filter(_models,function(models){return models.name!=undefined});
+                    _this.models = _this.models.concat(_models);
+                    defer.resolve(_this.models);
+                }
+            );
         },function(){
             defer.reject("Failed to load models");
         });
@@ -54,7 +62,7 @@ KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService,
     }
 
     this.removeAll = function(){
-        _this.models=[];
+        _this.models = [];
     };
 
 });

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/less/component.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/component.less b/webapp/app/less/component.less
index cb58e3f..b99c765 100644
--- a/webapp/app/less/component.less
+++ b/webapp/app/less/component.less
@@ -883,6 +883,12 @@ span.input-icon {
   color: black !important;
 }
 
+.callout.callout-warning {
+  background-color: #fefbed !important;
+  border-color: #f1e7bc !important;
+  color: black !important;
+}
+
 ul.messenger-theme-ice .messenger-message{
   color:#666667 !important;
 }
@@ -946,4 +952,10 @@ Angular 1.2.0 Animation
 }
 .model-design .btn-box-tool{
   font-size: 13px !important;
+}
+
+.models-main {
+  min-height: 100%;
+  background-color: #ecf0f5;
+  z-index: 800;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/partials/cubeDesigner/dimensions.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/dimensions.html b/webapp/app/partials/cubeDesigner/dimensions.html
index dbbc46d..1267b3f 100644
--- a/webapp/app/partials/cubeDesigner/dimensions.html
+++ b/webapp/app/partials/cubeDesigner/dimensions.html
@@ -183,7 +183,7 @@
                         <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 getColumnsByTable(newDimension.table)">
+                                    ng-model="newDimension.column[0]" ng-options="column.name as column.name for column in getDimColumnsByTable(newDimension.table)">
                                 <option value=""></option>
                             </select>
                         </div>
@@ -205,7 +205,7 @@
                                             <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 getColumnsByTable(newDimension.table)" >
+                                                    ng-options="columns.name as columns.name for columns in getDimColumnsByTable(newDimension.table)" >
                                                 <option value="">-- Select Column --</option>
                                             </select>
                                         </div>
@@ -244,7 +244,7 @@
                                     <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 getColumnsByTable(newDimension.table)" >
+                                                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"

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/partials/cubeDesigner/info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/info.html b/webapp/app/partials/cubeDesigner/info.html
index 3aaa314..bd6aed2 100644
--- a/webapp/app/partials/cubeDesigner/info.html
+++ b/webapp/app/partials/cubeDesigner/info.html
@@ -22,16 +22,13 @@
         <div class="form-group">
             <div class="row">
                 <label class="col-xs-12 col-sm-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>
+                    <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.project" disabled/>
+                           ng-model="cubeMetaFrame.model_name"/>
                     <span ng-if="state.mode=='view'">
-                        {{cubeMetaFrame.project}}
+                        {{cubeMetaFrame.model_name}}
                     </span>
                 </div>
             </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/partials/cubeDesigner/measures.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/measures.html b/webapp/app/partials/cubeDesigner/measures.html
index a260e28..ef8c8bf 100755
--- a/webapp/app/partials/cubeDesigner/measures.html
+++ b/webapp/app/partials/cubeDesigner/measures.html
@@ -148,7 +148,7 @@
                                     ng-if="newMeasure.function.parameter.type == 'column'"
                                     ng-model="newMeasure.function.parameter.value"
                                     ng-change="measureReturnTypeUpdate();"
-                                    ng-options="columns.name as columns.name for columns in getColumnsByTable(metaModel.model.fact_table)" >
+                                    ng-options="columns.name as columns.name for columns in getMetricColumnsByTable(metaModel.model.fact_table)" >
                                     <option value="">-- Select a Fact Table Column --</option>
                                 </select>
                             </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/partials/cubeDesigner/overview.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/overview.html b/webapp/app/partials/cubeDesigner/overview.html
index bbb5dc6..4bf14ff 100644
--- a/webapp/app/partials/cubeDesigner/overview.html
+++ b/webapp/app/partials/cubeDesigner/overview.html
@@ -23,8 +23,8 @@
                 <tbody>
                     <!--Project Name-->
                     <tr>
-                        <th>Project Name</th>
-                        <td>{{cubeMetaFrame.project}}</td>
+                        <th>Model Name</th>
+                        <td>{{metaModel.model.name}}</td>
                     </tr>
                     <!--Cube Name-->
                     <tr>
@@ -34,7 +34,7 @@
                     <!--Fact Table-->
                     <tr>
                         <th>Fact Table</th>
-                        <td class="tb-breakword">{{cubeMetaFrame.fact_table}}</td>
+                        <td class="tb-breakword">{{metaModel.model.fact_table}}</td>
                     </tr>
                     <!--Lookup Table-->
                     <tr>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/partials/models/_models.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/_models.html b/webapp/app/partials/models/_models.html
deleted file mode 100644
index ac433c1..0000000
--- a/webapp/app/partials/models/_models.html
+++ /dev/null
@@ -1,117 +0,0 @@
-<!--
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements.  See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership.  The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License.  You may obtain a copy of the License at
-*
-*     http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
--->
-
-<div class="page-header row">
-    <!--Project-->
-    <div class="col-xs-3">
-        <form ng-if="userService.isAuthorized()">
-            <div class="form-group">
-                <!--Project-->
-                <a class="btn btn-xs btn-info" href="projects" tooltip="Manage Project"><i class="fa fa-gears"></i></a>
-                <a class="btn btn-xs btn-primary" style="width: 29px" ng-if="userService.hasRole('ROLE_ADMIN')||userService.hasRole('ROLE_MODELER')&&kylinConfig.getDeployEnv()!=='PROD'"  tooltip="Add Project" ng-click="toCreateProj()">
-                    <i class="fa fa-plus"></i>
-                </a>
-            </div>
-        </form>
-    </div>
-    <!--Model Name-->
-    <div class="col-xs-3">
-        <form ng-submit="" style="display: inline" >
-            <span class="input-icon input-icon-right nav-search" style="font-size:14px;"><b>Model Name:</b>
-                <input type="text" placeholder="Filter ..." class="nav-search-input"  ng-model="listParams.modelName"/>
-                <i class="ace-icon fa fa-search blue"  ng-click="modelList.removeAll();list()"></i>
-            </span>
-        </form>
-    </div>
-    <div class="pull-right">
-        <a class="btn btn-primary btn-sm" href="models/add"  ng-if="userService.hasRole('ROLE_MODELER')" id="addModelButton"><i class="fa fa-plus"></i> Model</a>
-    </div>
-</div>
-<div ng-if="!loading && modelList.models.length == 0">
-    <div no-result text="No Model."></div>
-</div>
-<loading ng-if="loading" text="Loading Models..."></loading>
-
-<div ng-if="modelList.models.length > 0" class="dataTables_wrapper no-footer">
-    <div class="row">
-        <div class="col-xs-12"><label class="table-header-text">Models</label></div>
-    </div>
-    <table class="table table-striped table-bordered table-hover dataTable no-footer">
-        <!--Header-->
-        <thead>
-        <tr style="cursor: pointer">
-            <th ng-repeat="theaditem in modelConfig.theaditems"
-                ng-click="state.filterAttr= theaditem.attr;state.reverseColumn=theaditem.attr;state.filterReverse=!state.filterReverse;">
-                {{theaditem.name}}
-                <i ng-if="state.reverseColumn!= theaditem.attr"
-                   class="fa fa-unsorted"></i>
-                <i ng-if="state.reverseColumn== theaditem.attr && !state.filterReverse"
-                   class="fa fa-sort-asc"></i>
-                <i ng-if="state.reverseColumn== theaditem.attr && state.filterReverse"
-                   class="fa fa-sort-desc"></i>
-            </th>
-            <th>Actions</th>
-        </tr>
-        </thead>
-        <!--Body-->
-        <tbody ng-repeat="model in modelList.models | orderObjectBy:state.filterAttr:state.filterReverse">
-        <tr ng-class="{accordion:true}" style="cursor: pointer"  ng-click="model.showDetail=!model.showDetail;loadDetail(model)">
-            <td>
-                <i ng-show="!model.showDetail" class="fa fa-chevron-circle-right blue"></i>
-                <i ng-show="model.showDetail" class="fa fa-chevron-circle-down blue"></i>
-                {{ model.name}}
-            </td>
-            <td>
-                    {{ model.fact_table}}
-            </td>
-            <td>
-                    {{ model.last_modified | utcToConfigTimeZone}}
-            </td>
-            <td>
-                <div ng-click="$event.stopPropagation();" class="btn-group" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
-                    <button type="button" class="btn btn-default btn-xs dropdown-toggle"
-                            data-toggle="dropdown">
-                        Action <span class="ace-icon fa fa-caret-down icon-on-right"></span>
-                    </button>
-                    <ul class="dropdown-menu" role="menu">
-                        <li><a href="models/edit/{{model.name}}">Edit</a></li>
-                        <li ng-show="false" ng-if="userService.hasRole('ROLE_ADMIN')">
-                            <a ng-click="dropModel(model)" tooltip="Drop the model, related cubes and data permanently.">Drop</a></li>
-
-                    </ul>
-                </div>
-                <span ng-if="!(userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask))">
-                    N/A
-                </span>
-            </td>
-        </tr>
-        <tr ng-show="model.showDetail">
-            <td colspan="9" style="padding: 10px 30px 10px 30px;">
-                <div ng-include src="'partials/models/model_detail.html'"></div>
-            </td>
-        </tr>
-        </tbody>
-    </table>
-</div>
-
-
-<div class="row">
-    <div class="col-xs-12">
-        <kylin-pagination data="modelList.models" load-func="list" action="action"/>
-    </div>
-</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/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 7648f93..f19b9d3 100644
--- a/webapp/app/partials/models/model_schema.html
+++ b/webapp/app/partials/models/model_schema.html
@@ -16,11 +16,12 @@
 * limitations under the License.
 -->
 
-<div class="box box-primary model-design">
+<div class="box box-primary model-design" ng-hide="state.mode=='view'&&!model.name">
     <div class="box-header widget-header-blue widget-header-flat">
         <h4 class="box-title text-info">Model Designer</h4>
-        <div class="box-tools pull-right">
+        <div ng-if="state.mode=='view'" class="box-tools pull-right">
             <a class="btn btn-box-tool" tooltip="Edit Model" href="models/edit/{{model.name}}" data-widget="collapse"><i class="fa fa-edit"></i></a>
+            <a class="btn btn-box-tool" tooltip="Add Cube" href="cubes/add/{{model.name}}" data-widget="collapse"><i class="fa fa-cube"></i></a>
         </div>
     </div>
     <div class="box-body">
@@ -69,3 +70,14 @@
         </ng-form>
     </div>
 </div>
+
+<div ng-show="state.mode=='view'&&!model.name">
+    <div class="box box-primary">
+        <div class="box-header with-border">
+            <h3 class="box-title">No model selected</h3>
+        </div>
+        <div class="box-body">
+            Plese choose your model
+        </div><!-- /.box-body -->
+    </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/partials/models/models.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models.html b/webapp/app/partials/models/models.html
index 28a8fb3..355114a 100644
--- a/webapp/app/partials/models/models.html
+++ b/webapp/app/partials/models/models.html
@@ -15,21 +15,43 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 -->
-<div class="row">
+<div class="row models-main"  style="padding-top:10px;">
     <!--table_tree-->
-    <div class="col-xs-3">
-        <tabset>
+
+    <div class="col-xs-2">
+        <tabset class="nav-tabs-custom">
             <tab heading="Models" select="toggleTab(true);">
                 <div ng-include src="'partials/models/models_tree.html'"></div>
             </tab>
-            <tab heading="Data source"  select="toggleTab(false);">
+            <tab heading="Data Source"  select="toggleTab(false);">
                 <div ng-include src="'partials/tables/source_table_tree.html'"></div>
             </tab>
         </tabset>
     </div>
 
-    <div class="col-xs-9" style="padding-top:39px;">
-        <div ng-show="showModels" ng-include src="'partials/models/model_detail.html'"></div>
-        <div ng-show="!showModels" ng-include src="'partials/tables/table_detail.html'"></div>
+    <div ng-show="showModels" class="col-xs-2">
+        <div class="box box-primary">
+            <div class="box-header">
+                Cubes
+            </div>
+            <div class="box-body table-responsive no-padding">
+                <ul class="nav nav-list nav-pills nav-stacked">
+                    <li ng-repeat="cube in selectedCubes">
+                         <a>
+                             <span>{{cube.name}}</span>
+                         </a>
+                    </li>
+                </ul>
+            </div>
+        </div>
+    </div>
+    <div  ng-show="showModels"  class="col-xs-8 models-main">
+        <div ng-include src="'partials/models/model_detail.html'"></div>
+    </div>
+
+    <div ng-show="!showModels" class="col-xs-10 models-main">
+        <div ng-include src="'partials/tables/table_detail.html'"></div>
     </div>
+
+
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/partials/models/models_info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models_info.html b/webapp/app/partials/models/models_info.html
deleted file mode 100644
index f381077..0000000
--- a/webapp/app/partials/models/models_info.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!--
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements.  See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership.  The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License.  You may obtain a copy of the License at
-*
-*     http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
--->
-
-<div class="tree-border">
-    <div class="row">
-        <div class="col-xs-7">
-            <h3 class="text-info">Tables</h3>
-        </div>
-
-        <!--button-->
-        <div class="col-xs-5" style="padding-left: 0px;margin-top: 20px;">
-            <div class="pull-right">
-                <a class="btn btn-xs btn-primary" tooltip="Load Hive Table"  ng-if="userService.hasRole('ROLE_ADMIN')"  ng-click="openModal()"><i class="fa fa-download"></i></a>
-                <a class="btn btn-xs btn-success" tooltip="Refresh Tables" ng-click="aceSrcTbChanged()"><i class="fa fa-refresh"></i></a>
-            </div>
-        </div>
-
-    </div>
-    <div class="space-4"></div>
-    <!--tree-->
-    <div style="width:100%; height:{{window}}px; overflow:auto;">
-        <treecontrol ng-if="tableModel.selectedSrcDb.length > 0" class="tree-light"
-                     dirSelection="true"
-                     tree-model="tableModel.selectedSrcDb"
-                     options="tableModel.treeOptions"
-                     on-selection="showSelected(node)"
-                     selected-node="tableModel.selectedSrcTable">
-            {{node.name}} {{!!(node.datatype)?'(' + trimType(node.datatype) + ')' : ''}}
-        </treecontrol>
-    </div>
-</div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/partials/models/models_tree.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models_tree.html b/webapp/app/partials/models/models_tree.html
index 40b7c3a..58921ae 100644
--- a/webapp/app/partials/models/models_tree.html
+++ b/webapp/app/partials/models/models_tree.html
@@ -28,10 +28,8 @@
                 <a class="btn btn-xs btn-primary" href='models/add' tooltip="Create Model"  ng-if="userService.hasRole('ROLE_ADMIN')"><i class="fa fa-plus"></i></a>
             </div>
         </div>
-
-    </div>
     </div>
-    <div class="space-4 box-header with-border"></div>
+    <!--<div class="space-4 box-header with-border"></div>-->
     <!--tree-->
     <div style="width:100%; height:{{window}}px; overflow:auto;">
         <abn-tree
@@ -41,7 +39,7 @@
                 icon-expand       = "fa fa-plus"
                 icon-collapse     = "fa fa-minus"
                 expand-level      = "2"
-                initial-selection = "Vegetable">
+                initial-selection = "">
             ></abn-tree>
     </div>
 </div>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/partials/tables/table_detail.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/tables/table_detail.html b/webapp/app/partials/tables/table_detail.html
index b20825c..9801eb1 100644
--- a/webapp/app/partials/tables/table_detail.html
+++ b/webapp/app/partials/tables/table_detail.html
@@ -1,5 +1,5 @@
 <div  ng-controller="SourceMetaCtrl" class="nav-tabs-custom">
-    <div class="col-xs-9">
+    <div class="col-xs-12">
         <h3 class="text-info">Table Schema:{{ tableModel.selectedSrcTable.name}}</h3>
         <div class="tabbable nav-tabs-custom">
             <ul class="nav nav-tabs">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/app/routes.json
----------------------------------------------------------------------
diff --git a/webapp/app/routes.json b/webapp/app/routes.json
index 8ee6fc3..1accb01 100644
--- a/webapp/app/routes.json
+++ b/webapp/app/routes.json
@@ -10,7 +10,7 @@
         "url": "/cubes",
         "params": {
             "templateUrl": "partials/cubes/cubes.html",
-            "tab": "cubes",
+            "tab": "models",
             "controller": "CubesCtrl"
         }
     },
@@ -31,10 +31,10 @@
         }
     },
     {
-        "url": "/cubes/add",
+        "url": "/cubes/add/:modelName",
         "params": {
             "templateUrl": "partials/cubes/cube_edit.html",
-            "tab": "cubes",
+            "tab": "models",
             "controller": "CubeEditCtrl"
         }
     },
@@ -42,7 +42,7 @@
         "url": "/cubes/add/json",
         "params": {
             "templateUrl": "partials/cubes/cube_json_edit.html",
-            "tab": "cubes",
+            "tab": "models",
             "controller": "CubeEditCtrl"
         }
     },
@@ -50,7 +50,7 @@
         "url": "/cubes/edit/:cubeName/json",
         "params": {
             "templateUrl": "partials/cubes/cube_json_edit.html",
-            "tab": "cubes",
+            "tab": "models",
             "controller": "CubeEditCtrl"
         }
     },
@@ -58,7 +58,7 @@
         "url": "/cubes/edit/:cubeName",
         "params": {
             "templateUrl": "partials/cubes/cube_edit.html",
-            "tab": "cubes",
+            "tab": "models",
             "controller": "CubeEditCtrl"
         }
     },
@@ -66,7 +66,7 @@
         "url": "/cubes/:projectName/:cubeName",
         "params": {
             "templateUrl": "partials/cubes/cubes.html",
-            "tab": "cubes",
+            "tab": "models",
             "controller": "CubesCtrl"
         }
     },

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/b998dbc3/webapp/grunt.json
----------------------------------------------------------------------
diff --git a/webapp/grunt.json b/webapp/grunt.json
index 9a4499f..48ed483 100755
--- a/webapp/grunt.json
+++ b/webapp/grunt.json
@@ -59,6 +59,7 @@
                 "app/components/angular-chosen-localytics/chosen-spinner.css",
                 "app/components/nvd3/nv.d3.min.css",
                 "app/css/AdminLTE.css",
+                "app/css/skins/_all-skins.min.css",
                 "app/components/bootstrap-sweetalert/lib/sweet-alert.css",
                 "tmp/css/styles.css"
             ],