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

[30/52] [abbrv] incubator-kylin git commit: move cube action from cubes.js to cube.js

move cube action from cubes.js to cube.js


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

Branch: refs/heads/0.8.0
Commit: 2cb6e0a20b451b52917ff5979f06f30c20a2ba54
Parents: b998dbc
Author: jiazhong <ji...@ebay.com>
Authored: Tue Mar 24 20:04:31 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:52 2015 +0800

----------------------------------------------------------------------
 webapp/app/js/controllers/cube.js               | 355 ++++++++++++++++++-
 webapp/app/js/controllers/cubeEdit.js           |  24 +-
 webapp/app/js/controllers/models.js             |  34 ++
 webapp/app/js/model/modelList.js                |  14 +
 webapp/app/less/component.less                  |   9 +-
 .../app/partials/cubeDesigner/dimensions.html   |   2 +-
 webapp/app/partials/cubes/cube_detail.html      |  44 ++-
 webapp/app/partials/cubes/cubes.html            |   1 -
 webapp/app/partials/jobs/job_submit.html        |   1 +
 webapp/app/partials/models/models.html          |  31 +-
 10 files changed, 457 insertions(+), 58 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/js/controllers/cube.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cube.js b/webapp/app/js/controllers/cube.js
index 2765a45..2585345 100755
--- a/webapp/app/js/controllers/cube.js
+++ b/webapp/app/js/controllers/cube.js
@@ -18,7 +18,7 @@
 
 'use strict';
 
-KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService, CubeService, TableService, GraphService, UserService,SweetAlert) {
+KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService, CubeService, TableService, GraphService, UserService,SweetAlert,loadingRequest,ModelList,$modal) {
     $scope.newAccess = null;
     $scope.state = {jsonEdit: false};
 
@@ -102,4 +102,357 @@ KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService,
             });
         }
     };
+
+//    Cube Action
+    $scope.enable = function (cube) {
+        SweetAlert.swal({
+            title: '',
+            text: 'Are you sure to enable the cube? Please note: if cube schema is changed in the disabled period, all segments of the cube will be discarded due to data and schema mismatch.',
+            type: '',
+            showCancelButton: true,
+            confirmButtonColor: '#DD6B55',
+//                confirmButtonText: "Yes",
+            closeOnConfirm: true
+        }, function(isConfirm) {
+            if(isConfirm){
+
+                loadingRequest.show();
+                CubeService.enable({cubeId: cube.name}, {}, function (result) {
+
+                    loadingRequest.hide();
+                    cube.status = 'READY';
+                    SweetAlert.swal('Success!', 'Enable job was submitted successfully', 'success');
+                },function(e){
+
+                    loadingRequest.hide();
+                    if(e.data&& e.data.exception){
+                        var message =e.data.exception;
+                        var msg = !!(message) ? message : 'Failed to take action.';
+                        SweetAlert.swal('Oops...', msg, 'error');
+                    }else{
+                        SweetAlert.swal('Oops...', "Failed to take action.", 'error');
+                    }
+                });
+            }
+        });
+    };
+
+    $scope.purge = function (cube) {
+        SweetAlert.swal({
+            title: '',
+            text: 'Are you sure to purge the cube? ',
+            type: '',
+            showCancelButton: true,
+            confirmButtonColor: '#DD6B55',
+            confirmButtonText: "Yes",
+            closeOnConfirm: true
+        }, function(isConfirm) {
+            if(isConfirm){
+
+                loadingRequest.show();
+                CubeService.purge({cubeId: cube.name}, {}, function (result) {
+
+                    loadingRequest.hide();
+//                    CubeList.removeAll();
+//                    $scope.reload();
+                    SweetAlert.swal('Success!', 'Purge job was submitted successfully', 'success');
+                },function(e){
+                    loadingRequest.hide();
+                    if(e.data&& e.data.exception){
+                        var message =e.data.exception;
+                        var msg = !!(message) ? message : 'Failed to take action.';
+                        SweetAlert.swal('Oops...', msg, 'error');
+                    }else{
+                        SweetAlert.swal('Oops...', "Failed to take action.", 'error');
+                    }
+                });
+            }
+        });
+    }
+
+
+    $scope.disable = function (cube) {
+
+        SweetAlert.swal({
+            title: '',
+            text: 'Are you sure to disable the cube? ',
+            type: '',
+            showCancelButton: true,
+            confirmButtonColor: '#DD6B55',
+            confirmButtonText: "Yes",
+            closeOnConfirm: true
+        }, function(isConfirm) {
+            if(isConfirm){
+
+                loadingRequest.show();
+                CubeService.disable({cubeId: cube.name}, {}, function (result) {
+
+                    loadingRequest.hide();
+                    cube.status = 'DISABLED';
+                    SweetAlert.swal('Success!', 'Disable job was submitted successfully', 'success');
+                },function(e){
+
+                    loadingRequest.hide();
+                    if(e.data&& e.data.exception){
+                        var message =e.data.exception;
+                        var msg = !!(message) ? message : 'Failed to take action.';
+                        SweetAlert.swal('Oops...', msg, 'error');
+                    }else{
+                        SweetAlert.swal('Oops...', "Failed to take action.", 'error');
+                    }
+                });
+            }
+
+        });
+    };
+
+
+    $scope.dropCube = function (cube) {
+
+        SweetAlert.swal({
+            title: '',
+            text: " Once it's dropped, your cube’s metadata and data will be cleaned up and can’t be restored back. ",
+            type: '',
+            showCancelButton: true,
+            confirmButtonColor: '#DD6B55',
+            confirmButtonText: "Yes",
+            closeOnConfirm: true
+        }, function(isConfirm) {
+            if(isConfirm){
+
+                loadingRequest.show();
+                CubeService.drop({cubeId: cube.name}, {}, function (result) {
+
+                    loadingRequest.hide();
+//                    CubeList.removeCube(cube);
+                    SweetAlert.swal('Success!', 'Cube drop is done successfully', 'success');
+
+                },function(e){
+
+                    loadingRequest.hide();
+                    if(e.data&& e.data.exception){
+                        var message =e.data.exception;
+                        var msg = !!(message) ? message : 'Failed to take action.';
+                        SweetAlert.swal('Oops...', msg, 'error');
+                    }else{
+                        SweetAlert.swal('Oops...', "Failed to take action.", 'error');
+                    }
+                });
+            }
+
+        });
+    };
+
+    $scope.startJobSubmit = function (cube) {
+        $scope.metaModel.model = ModelList.getModelByCube(cube.name);
+        if ($scope.metaModel.model.name) {
+            if ($scope.metaModel.model.partition_desc.partition_date_column) {
+                $modal.open({
+                    templateUrl: 'jobSubmit.html',
+                    controller: jobSubmitCtrl,
+                    resolve: {
+                        cube: function () {
+                            return cube;
+                        },
+                        metaModel:function(){
+                            return $scope.metaModel;
+                        },
+                        buildType: function () {
+                            return 'BUILD';
+                        }
+                    }
+                });
+            }
+            else {
+
+                SweetAlert.swal({
+                    title: '',
+                    text: "Are you sure to start the build? ",
+                    type: '',
+                    showCancelButton: true,
+                    confirmButtonColor: '#DD6B55',
+                    confirmButtonText: "Yes",
+                    closeOnConfirm: true
+                }, function(isConfirm) {
+                    if(isConfirm){
+
+                        loadingRequest.show();
+                        CubeService.rebuildCube(
+                            {
+                                cubeId: cube.name
+                            },
+                            {
+                                buildType: 'BUILD',
+                                startTime: 0,
+                                endTime: 0
+                            }, function (job) {
+
+                                loadingRequest.hide();
+                                SweetAlert.swal('Success!', 'Rebuild job was submitted successfully', 'success');
+                            },function(e){
+
+                                loadingRequest.hide();
+                                if(e.data&& e.data.exception){
+                                    var message =e.data.exception;
+                                    var msg = !!(message) ? message : 'Failed to take action.';
+                                    SweetAlert.swal('Oops...', msg, 'error');
+                                }else{
+                                    SweetAlert.swal('Oops...', "Failed to take action.", 'error');
+                                }
+                            });
+                    }
+
+                });
+            }
+        }
+    };
+
+    $scope.startRefresh = function (cube) {
+            $modal.open({
+                templateUrl: 'jobRefresh.html',
+                controller: jobSubmitCtrl,
+                resolve: {
+                    cube: function () {
+                        return cube.detail;
+                    },
+                    metaModel:function(){
+                        return $scope.metaModel;
+                    },
+                    buildType: function () {
+                        return 'BUILD';
+                    }
+                }
+            });
+
+    };
+
+    $scope.startMerge = function (cube) {
+            $modal.open({
+                templateUrl: 'jobMerge.html',
+                controller: jobSubmitCtrl,
+                resolve: {
+                    cube: function () {
+                        return cube.detail;
+                    },
+                    metaModel:function(){
+                        return $scope.metaModel;
+                    },
+                    buildType: function () {
+                        return 'MERGE';
+                    }
+                }
+            });
+    }
+
+
 });
+
+
+var jobSubmitCtrl = function ($scope, $modalInstance, CubeService, MessageService, $location, cube,metaModel, buildType,SweetAlert,loadingRequest) {
+    $scope.cube = cube;
+    $scope.metaModel={
+        model:metaModel.model
+    }
+    $scope.jobBuildRequest = {
+        buildType: buildType,
+        startTime: 0,
+        endTime: 0
+    };
+    $scope.message = "";
+
+    $scope.rebuild = function (jobsubmit) {
+
+        $scope.message = null;
+        $scope.jobBuildRequest.startTime = new Date($scope.jobBuildRequest.startTime).getTime();
+        $scope.jobBuildRequest.endTime = new Date($scope.jobBuildRequest.endTime).getTime();
+
+        if ($scope.jobBuildRequest.startTime >= $scope.jobBuildRequest.endTime) {
+            $scope.message = "WARNING: End time should be later than the start time.";
+
+            //rollback date setting
+            if(jobsubmit){
+                $scope.rebuildRollback();
+            }
+            return;
+        }
+
+        loadingRequest.show();
+        CubeService.rebuildCube({cubeId: cube.name}, $scope.jobBuildRequest, function (job) {
+
+            loadingRequest.hide();
+            $modalInstance.dismiss('cancel');
+            SweetAlert.swal('Success!', 'Rebuild job was submitted successfully', 'success');
+        },function(e){
+
+            //rollback date setting
+            if(jobsubmit){
+                $scope.rebuildRollback();
+            }
+
+            loadingRequest.hide();
+            if(e.data&& e.data.exception){
+                var message =e.data.exception;
+                var msg = !!(message) ? message : 'Failed to take action.';
+                SweetAlert.swal('Oops...', msg, 'error');
+            }else{
+                SweetAlert.swal('Oops...', "Failed to take action.", 'error');
+            }
+        });
+    };
+
+    $scope.rebuildRollback = function(){
+        $scope.jobBuildRequest.endTime+=new Date().getTimezoneOffset()*60000;
+    }
+
+    // used by cube segment refresh
+    $scope.segmentSelected = function (selectedSegment) {
+        $scope.jobBuildRequest.startTime = 0;
+        $scope.jobBuildRequest.endTime = 0;
+
+        if (selectedSegment.date_range_start) {
+            $scope.jobBuildRequest.startTime = selectedSegment.date_range_start;
+        }
+
+        if (selectedSegment.date_range_end) {
+            $scope.jobBuildRequest.endTime = selectedSegment.date_range_end;
+        }
+    };
+
+    // used by cube segments merge
+    $scope.mergeStartSelected = function (mergeStartSeg) {
+        $scope.jobBuildRequest.startTime = 0;
+
+        if (mergeStartSeg.date_range_start) {
+            $scope.jobBuildRequest.startTime = mergeStartSeg.date_range_start;
+        }
+    };
+
+    $scope.mergeEndSelected = function (mergeEndSeg) {
+        $scope.jobBuildRequest.endTime = 0;
+
+        if (mergeEndSeg.date_range_end) {
+            $scope.jobBuildRequest.endTime = mergeEndSeg.date_range_end;
+        }
+    };
+
+    $scope.updateDate = function() {
+
+
+//        if ($scope.cube.detail.partition_desc.cube_partition_type=='UPDATE_INSERT')
+//        {
+//            $scope.jobBuildRequest.startTime=$scope.formatDate($scope.jobBuildRequest.startTime);
+//        }
+        $scope.jobBuildRequest.endTime=$scope.formatDate($scope.jobBuildRequest.endTime);
+    };
+
+    $scope.formatDate = function(timestemp) {
+        var dateStart = new Date(timestemp);
+        dateStart = (dateStart.getFullYear() + "-" + (dateStart.getMonth() + 1) + "-" + dateStart.getDate());
+        //switch selected time to utc timestamp
+        return new Date(moment.utc(dateStart, "YYYY-MM-DD").format()).getTime();
+    };
+    $scope.cancel = function () {
+        $modalInstance.dismiss('cancel');
+    };
+};
+

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/js/controllers/cubeEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeEdit.js b/webapp/app/js/controllers/cubeEdit.js
index 01e1623..afc5efe 100755
--- a/webapp/app/js/controllers/cubeEdit.js
+++ b/webapp/app/js/controllers/cubeEdit.js
@@ -19,10 +19,10 @@
 'use strict';
 
 
-KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $location, $templateCache, $interpolate, MessageService, TableService, CubeDescService, CubeService, loadingRequest, SweetAlert,$log,cubeConfig,CubeDescModel,MetaModel,TableModel,ModelDescService) {
+KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $location, $templateCache, $interpolate, MessageService, TableService, CubeDescService, CubeService, loadingRequest, SweetAlert,$log,cubeConfig,CubeDescModel,MetaModel,TableModel,ModelDescService,ModelList) {
     $scope.cubeConfig = cubeConfig;
 
-    $log.info("model name:"+$routeParams.modelName);
+    // when add cube will transfer model Name
     var modelName = $routeParams.modelName;
 
     //add or edit ?
@@ -114,6 +114,9 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         CubeDescService.get({cube_name: $routeParams.cubeName}, function (detail) {
             if (detail.length > 0) {
                 $scope.cubeMetaFrame = detail[0];
+                $scope.metaModel ={
+                    model : ModelList.getModel($scope.cubeMetaFrame.model_name)
+                }
                 $scope.state.cubeSchema = angular.toJson($scope.cubeMetaFrame, true);
             }
         });
@@ -122,24 +125,13 @@ KylinApp.controller('CubeEditCtrl', function ($scope, $q, $routeParams, $locatio
         $scope.cubeMetaFrame = CubeDescModel.createNew();
 //        MetaModel.initModel();
 //        $scope.metaModel = MetaModel;
+        $scope.metaModel ={
+            model : ModelList.getModel(modelName)
+        }
         $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 () {
     };

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/js/controllers/models.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/models.js b/webapp/app/js/controllers/models.js
index f40e8ec..5e9db87 100644
--- a/webapp/app/js/controllers/models.js
+++ b/webapp/app/js/controllers/models.js
@@ -24,6 +24,8 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
         //tree data
         $scope.models_treedata=[];
         $scope.selectedCubes = [];
+        $scope.cubeSelected = false;
+        $scope.cube = {};
 
         $scope.showModels=true;
 
@@ -83,6 +85,7 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
                         onSelect:function(branch){
                          // set selecte model
                             $scope.model=branch.data;
+                            $scope.cubeSelected = false;
                             $scope.selectedCubes = branch.data.cubes;
                         }
                     };
@@ -94,6 +97,36 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
                                 data:cube,
                                 onSelect:function(branch){
                                     console.log("cube selected:"+branch.data);
+                                    $scope.cubeSelected = true;
+//                                    $scope.cubeMetaFrame = branch.data;
+                                    $scope.cube = branch.data;
+
+                                    CubeDescService.get({cube_name: cube.name}, {}, function (detail) {
+                                        if (detail.length > 0&&detail[0].hasOwnProperty("name")) {
+                                            $scope.cubeMetaFrame = detail[0];
+                                            $scope.cube.detail = detail[0];
+                                            $scope.metaModel ={
+                                                model : $scope.model
+                                            }
+//                                            ModelDescService.get({model_name: cube.detail.model_name}, function (model) {
+//                                                cube.model = model;
+//                                                $scope.metaModel.model= $scope.model;
+////                                                defer.resolve(cube.detail);
+//                                            });
+
+                                        }else{
+                                            SweetAlert.swal('Oops...', "No cube detail info loaded.", 'error');
+                                        }
+                                    }, function (e) {
+                                        if(e.data&& e.data.exception){
+                                            var message =e.data.exception;
+                                            var msg = !!(message) ? message : 'Failed to take action.';
+                                            SweetAlert.swal('Oops...', msg, 'error');
+                                        }else{
+                                            SweetAlert.swal('Oops...', "Failed to take action.", 'error');
+                                        }
+                                    });
+
                                     // set selecte model
                                 }
                             }
@@ -113,6 +146,7 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
                 ModelList.removeAll();
                 //init selected model
                 $scope.model = {};
+                $scope.selectedCubes=[];
                 $scope.init();
         });
 

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/js/model/modelList.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/modelList.js b/webapp/app/js/model/modelList.js
index e5be622..6652611 100644
--- a/webapp/app/js/model/modelList.js
+++ b/webapp/app/js/model/modelList.js
@@ -61,6 +61,20 @@ KylinApp.service('ModelList',function(ModelService,CubeService,$q,AccessService,
         }
     }
 
+    this.getModel = function(modelName){
+      return  _.find(_this.models,function(unit){
+            return unit.name == modelName;
+        })
+    }
+
+    this.getModelByCube = function(cubeName){
+        return  _.find(_this.models,function(model){
+            return _.some(model.cubes,function(_cube){
+                return _cube.name == cubeName;
+            });
+        })
+    }
+
     this.removeAll = function(){
         _this.models = [];
     };

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/less/component.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/component.less b/webapp/app/less/component.less
index b99c765..e9f1a4c 100644
--- a/webapp/app/less/component.less
+++ b/webapp/app/less/component.less
@@ -953,9 +953,6 @@ 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
+.dropdown-menu a{
+  cursor: pointer;
+}

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/partials/cubeDesigner/dimensions.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubeDesigner/dimensions.html b/webapp/app/partials/cubeDesigner/dimensions.html
index 1267b3f..5a025f4 100644
--- a/webapp/app/partials/cubeDesigner/dimensions.html
+++ b/webapp/app/partials/cubeDesigner/dimensions.html
@@ -38,9 +38,9 @@
             </button>
         </div>
         <div class="col-xs-6" ng-if="state.mode!='edit'">
-            <b>Dimensions</b>
         </div>
         <div class="col-xs-6">
+            <b>Dimensions</b>
             <span class="pull-right input-icon input-icon-right nav-search" style="margin-left: 22px;">
                 <input type="text" placeholder="Filter ..." class="nav-search-input" ng-model="dimState.filter"/>
                 <i class="ace-icon fa fa-search nav-search-icon"></i>

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/partials/cubes/cube_detail.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cube_detail.html b/webapp/app/partials/cubes/cube_detail.html
index 59f2d69..39c727d 100755
--- a/webapp/app/partials/cubes/cube_detail.html
+++ b/webapp/app/partials/cubes/cube_detail.html
@@ -21,9 +21,9 @@
         <li class="{{(!cube.visiblePage || cube.visiblePage=='metadata')? 'active':''}}">
             <a href="" ng-click="cube.visiblePage='metadata'">Grid</a>
         </li>
-        <li class="{{cube.visiblePage=='graph'? 'active':''}}">
-            <a href="" ng-click="cube.visiblePage='graph';buildGraph(cube);">Visualization</a>
-        </li>
+        <!--<li class="{{cube.visiblePage=='graph'? 'active':''}}">-->
+            <!--<a href="" ng-click="cube.visiblePage='graph';buildGraph(cube);">Visualization</a>-->
+        <!--</li>-->
         <li class="{{cube.visiblePage=='sql'? 'active':''}}">
             <a href="" ng-click="cube.visiblePage='sql';getCubeSql(cube)">SQL</a>
         </li>
@@ -31,10 +31,10 @@
             ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(cube, 16) && !newAccess">
             <a href="" ng-click="cube.visiblePage='json';">JSON(Cube)</a>
         </li>
-      <li class="{{cube.visiblePage=='json_model'? 'active':''}}"
-          ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(cube, 16) && !newAccess">
-        <a href="" ng-click="cube.visiblePage='json_model';">JSON(Model)</a>
-      </li>
+      <!--<li class="{{cube.visiblePage=='json_model'? 'active':''}}"-->
+          <!--ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(cube, 16) && !newAccess">-->
+        <!--<a href="" ng-click="cube.visiblePage='json_model';">JSON(Model)</a>-->
+      <!--</li>-->
         <li class="{{cube.visiblePage=='access'? 'active':''}}">
             <a href="" ng-click="cube.visiblePage='access';listAccess(cube, 'CubeInstance');">Access</a>
         </li>
@@ -46,6 +46,24 @@
             ng-if="userService.hasRole('ROLE_ADMIN')">
             <a href="" ng-click="cube.visiblePage='hbase';getHbaseInfo(cube)">HBase</a>
         </li>
+        <li class="dropdown open">
+            <a class="dropdown-toggle" data-toggle="dropdown" href="#" aria-expanded="true">
+                Action <span class="caret"></span>
+            </a>
+            <ul class="dropdown-menu">
+                <li ng-if="cube.status=='DISABLED' && userService.hasRole('ROLE_ADMIN') ">
+                    <a ng-click="dropCube(cube)" tooltip="Drop the cube, related jobs and data permanently.">Drop</a></li>
+                <li ng-if="cube.status=='DISABLED' && (userService.hasRole('ROLE_ADMIN') || hasPermission(cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask))">
+                    <a href="cubes/edit/{{cube.name}}">Edit</a></li>
+                <li><a ng-click="startJobSubmit(cube);">Build</a></li>
+                <li><a ng-click="startRefresh(cube)">Refresh</a></li>
+                <li><a ng-click="startMerge(cube)">Merge</a></li>
+                <li ng-if="cube.status!='DISABLED'"><a ng-click="disable(cube)">Disable</a></li>
+                <li ng-if="cube.status=='DISABLED'"><a ng-click="enable(cube)">Enable</a></li>
+                <li ng-if="cube.status=='DISABLED'"><a ng-click="purge(cube)">Purge</a></li>
+            </ul>
+        </li>
+
     </ul>
 
     <div class="cube-detail" ng-if="!cube.visiblePage || cube.visiblePage=='metadata'">
@@ -68,12 +86,12 @@
              style="background-color: white;border: 0px">{{angular.toJson(cleanStatus(cube.detail), true)}}</pre>
     </div>
 
-    <div ng-show="cube.visiblePage=='json_model'" class="cube-detail">
-          <pre ng-if="!state.jsonEdit"
-               style="background-color: white;border: 0px">{{angular.toJson(cleanStatus(cube.model), true)}}</pre>
-    </div>
-    <div ng-show="cube.visiblePage=='graph'" id="cube_graph_{{cube.name}}" class="cube-detail cube_graph">
-    </div>
+    <!--<div ng-show="cube.visiblePage=='json_model'" class="cube-detail">-->
+          <!--<pre ng-if="!state.jsonEdit"-->
+               <!--style="background-color: white;border: 0px">{{angular.toJson(cleanStatus(model), true)}}</pre>-->
+    <!--</div>-->
+    <!--<div ng-show="cube.visiblePage=='graph'" id="cube_graph_{{cube.name}}" class="cube-detail cube_graph">-->
+    <!--</div>-->
 
     <div class="cube-detail" ng-if="cube.visiblePage=='access'">
         <div class="row">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/partials/cubes/cubes.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cubes.html b/webapp/app/partials/cubes/cubes.html
index 4c21d9a..f888c88 100644
--- a/webapp/app/partials/cubes/cubes.html
+++ b/webapp/app/partials/cubes/cubes.html
@@ -114,7 +114,6 @@
                         <li ng-if="cube.status!='DISABLED'"><a ng-click="disable(cube)">Disable</a></li>
                         <li ng-if="cube.status=='DISABLED'"><a ng-click="enable(cube)">Enable</a></li>
                         <li ng-if="cube.status=='DISABLED'"><a ng-click="purge(cube)">Purge</a></li>
-
                     </ul>
                 </div>
                 <span ng-if="!(userService.hasRole('ROLE_ADMIN') || hasPermission(cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask))">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/partials/jobs/job_submit.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/jobs/job_submit.html b/webapp/app/partials/jobs/job_submit.html
index 1036dee..7887680 100644
--- a/webapp/app/partials/jobs/job_submit.html
+++ b/webapp/app/partials/jobs/job_submit.html
@@ -19,6 +19,7 @@
 <script type="text/ng-template" id="jobSubmit.html">
     <div class="modal-header">
         <h4 tooltip="submit">CUBE BUILD CONFIRM</h4>
+        <span>{{metaModel.model.partition_desc.partition_date_column}}</span>
     </div>
     <div class="modal-body" style="background-color: white">
         <div ng-if="metaModel.model.partition_desc.partition_date_column" class="row">

http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/2cb6e0a2/webapp/app/partials/models/models.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/models/models.html b/webapp/app/partials/models/models.html
index 355114a..e4e7d57 100644
--- a/webapp/app/partials/models/models.html
+++ b/webapp/app/partials/models/models.html
@@ -18,7 +18,7 @@
 <div class="row models-main"  style="padding-top:10px;">
     <!--table_tree-->
 
-    <div class="col-xs-2">
+    <div class="col-xs-3">
         <tabset class="nav-tabs-custom">
             <tab heading="Models" select="toggleTab(true);">
                 <div ng-include src="'partials/models/models_tree.html'"></div>
@@ -28,30 +28,21 @@
             </tab>
         </tabset>
     </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-show="showModels&&!cubeSelected"  class="col-xs-9 models-main">
         <div ng-include src="'partials/models/model_detail.html'"></div>
     </div>
+    <div  ng-show="showModels&&cubeSelected"  class="col-xs-9 models-main">
+        <div ng-include src="'partials/cubes/cube_detail.html'"></div>
+    </div>
 
-    <div ng-show="!showModels" class="col-xs-10 models-main">
+    <div ng-show="!showModels" class="col-xs-9 models-main">
         <div ng-include src="'partials/tables/table_detail.html'"></div>
     </div>
 
 
 </div>
+
+<div ng-include="'partials/jobs/job_submit.html'"></div>
+<div ng-include="'partials/jobs/job_refresh.html'"></div>
+<div ng-include="'partials/jobs/job_merge.html'"></div>
+<div ng-include="'partials/projects/project_create.html'"></div>
\ No newline at end of file