You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by zh...@apache.org on 2016/12/20 07:43:47 UTC

[1/2] kylin git commit: KYLIN-2287 Speed up model and cube list load in Web

Repository: kylin
Updated Branches:
  refs/heads/master f50c0c873 -> c72e23202


KYLIN-2287 Speed up model and cube list load in Web

Signed-off-by: zhongjian <ji...@163.com>


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

Branch: refs/heads/master
Commit: 64a0a5943c034ea6f9cdc6d179d8be9da64fe5ac
Parents: f50c0c8
Author: kangkaisen <ka...@live.com>
Authored: Wed Dec 14 20:08:14 2016 +0800
Committer: zhongjian <ji...@163.com>
Committed: Tue Dec 20 15:12:54 2016 +0800

----------------------------------------------------------------------
 webapp/app/js/controllers/cubeSchema.js     |  25 +-
 webapp/app/js/controllers/cubes.js          | 318 ++++++++++-------------
 webapp/app/js/controllers/models.js         |  54 ++--
 webapp/app/js/model/cubeListModel.js        |   4 -
 webapp/app/js/model/modelsManager.js        |  49 +---
 webapp/app/partials/cubes/cubes.html        |  12 +-
 webapp/app/partials/models/models_tree.html |  16 +-
 7 files changed, 215 insertions(+), 263 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/64a0a594/webapp/app/js/controllers/cubeSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeSchema.js b/webapp/app/js/controllers/cubeSchema.js
index 357b6af..af8ee7c 100755
--- a/webapp/app/js/controllers/cubeSchema.js
+++ b/webapp/app/js/controllers/cubeSchema.js
@@ -45,18 +45,6 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
         $scope.state = {mode: "view"};
     }
 
-  var queryParam = {offset: 0, limit: 65535};
-
-  CubeService.list(queryParam, function (all_cubes) {
-    if($scope.allCubes.length > 0){
-      $scope.allCubes.splice(0,$scope.allCubes.length);
-    }
-
-    for (var i = 0; i < all_cubes.length; i++) {
-      $scope.allCubes.push(all_cubes[i].name.toUpperCase());
-    }
-  });
-
     $scope.$watch('cubeMetaFrame', function (newValue, oldValue) {
         if(!newValue){
             return;
@@ -198,6 +186,19 @@ KylinApp.controller('CubeSchemaCtrl', function ($scope, QueryService, UserServic
     };
 
   $scope.check_cube_info = function(){
+
+    var queryParam = {offset: 0, limit: 65535};
+
+    CubeService.list(queryParam, function (all_cubes) {
+      if($scope.allCubes.length > 0){
+        $scope.allCubes.splice(0,$scope.allCubes.length);
+      }
+
+      for (var i = 0; i < all_cubes.length; i++) {
+        $scope.allCubes.push(all_cubes[i].name.toUpperCase());
+      }
+    });
+
     if(($scope.state.mode === "edit") &&$scope.cubeMode=="addNewCube"&&($scope.allCubes.indexOf($scope.cubeMetaFrame.name.toUpperCase()) >= 0)){
       SweetAlert.swal('Oops...', "The cube named [" + $scope.cubeMetaFrame.name.toUpperCase() + "] already exists", 'warning');
       return false;

http://git-wip-us.apache.org/repos/asf/kylin/blob/64a0a594/webapp/app/js/controllers/cubes.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubes.js b/webapp/app/js/controllers/cubes.js
index b672d3f..cbdbb7d 100644
--- a/webapp/app/js/controllers/cubes.js
+++ b/webapp/app/js/controllers/cubes.js
@@ -79,43 +79,6 @@ KylinApp.controller('CubesCtrl', function ($scope, $q, $routeParams, $location,
 
       return CubeList.list(queryParam).then(function (resp) {
         angular.forEach($scope.cubeList.cubes,function(cube,index){
-          cube.streaming = false;
-          CubeDescService.query({cube_name: cube.name}, {}, function (detail) {
-            if (detail.length > 0 && detail[0].hasOwnProperty("name")) {
-              cube.detail = detail[0];
-              ModelService.list({projectName:$scope.projectModel.selectedProject,modelName:cube.detail.model_name}, function (_models) {
-                if(_models && _models.length){
-                  for(var i=0;i<=_models.length;i++){
-                    if(_models[i].name == cube.detail.model_name){
-                      cube.model = _models[i];
-                      var factTable = cube.model.fact_table;
-                      TableService.get({tableName:factTable},function(table){
-                        if(table && table.source_type == 1){
-                          cube.streaming = true;
-                        }
-                      })
-                      break;
-                    }
-                  }
-                }
-
-              })
-              //cube.model = modelsManager.getModel(cube.detail.model_name);
-
-              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');
-            }
-          });
         })
 
         $scope.loading = false;
@@ -331,140 +294,139 @@ KylinApp.controller('CubesCtrl', function ($scope, $q, $routeParams, $location,
     };
 
     $scope.startJobSubmit = function (cube) {
-      $scope.loadDetail(cube);
-      // for streaming cube build tip
-      if(cube.streaming){
-
-        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.rebuildStreamingCube(
-              {
-                cubeId: cube.name
-              },
-              {
-                sourceOffsetStart:0,
-                sourceOffsetEnd:'9223372036854775807',
-                buildType:'BUILD'
-              }, 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.loadDetail(cube).then(function () {
+        $scope.metaModel={
+          model:cube.model
+        };
+
+        TableService.get({tableName:$scope.metaModel.model.fact_table},function(table){
+          if(table && table.source_type == 1){
+            cube.streaming = true;
+          }
+
+          // for streaming cube build tip
+          if(cube.streaming){
+            $modal.open({
+              templateUrl: 'streamingBuild.html',
+              controller: streamingBuildCtrl,
+              resolve: {
+                cube: function () {
+                  return cube;
+                },
+                metaModel:function(){
+                  return $scope.metaModel;
+                },
+                buildType: function () {
+                  return 'BUILD';
+                },
+                scope:function(){
+
+                  return $scope;
                 }
+              }
             });
+            return;
           }
-        })
-        return;
-      }
 
-      $scope.metaModel={
-        model:modelsManager.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';
-              },
-              scope:function(){
-
-                return $scope;
-              }
+          //for batch cube build tip
+          if ($scope.metaModel.model.name) {
+
+            //for partition cube build tip
+            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';
+                  },
+                  scope:function(){
+                    return $scope;
+                  }
+                }
+              });
             }
-          });
-        }
-        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){
+            //for not partition cube build tip
+            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');
+                      }
+                    });
+                }
 
-              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) {
-      $scope.metaModel={
-        model:modelsManager.getModelByCube(cube.name)
-      };
-      $modal.open({
-        templateUrl: 'jobRefresh.html',
-        controller: jobSubmitCtrl,
-        resolve: {
-          cube: function () {
-            return cube;
-          },
-          metaModel:function(){
-            return $scope.metaModel;
-          },
-          buildType: function () {
-            return 'REFRESH';
-          },
-          scope:function(){
-            return $scope;
+
+      $scope.loadDetail(cube).then(function () {
+        $scope.metaModel={
+          model:cube.model
+        };
+        $modal.open({
+          templateUrl: 'jobRefresh.html',
+          controller: jobSubmitCtrl,
+          resolve: {
+            cube: function () {
+              return cube;
+            },
+            metaModel:function(){
+              return $scope.metaModel;
+            },
+            buildType: function () {
+              return 'REFRESH';
+            },
+            scope:function(){
+              return $scope;
+            }
           }
+        });
         }
-      });
+      )
 
     };
 
@@ -493,27 +455,29 @@ KylinApp.controller('CubesCtrl', function ($scope, $q, $routeParams, $location,
       $location.path("cubes/edit/" + cube.name);
     }
     $scope.startMerge = function (cube) {
-      $scope.metaModel={
-        model:modelsManager.getModelByCube(cube.name)
-      };
-      $modal.open({
-        templateUrl: 'jobMerge.html',
-        controller: jobSubmitCtrl,
-        resolve: {
-          cube: function () {
-            return cube;
-          },
-          metaModel:function(){
-            return $scope.metaModel;
-          },
-          buildType: function () {
-            return 'MERGE';
-          },
-          scope:function(){
-            return $scope;
+      $scope.loadDetail(cube).then(function () {
+        $scope.metaModel={
+          model:cube.model
+        };
+        $modal.open({
+          templateUrl: 'jobMerge.html',
+          controller: jobSubmitCtrl,
+          resolve: {
+            cube: function () {
+              return cube;
+            },
+            metaModel:function(){
+              return $scope.metaModel;
+            },
+            buildType: function () {
+              return 'MERGE';
+            },
+            scope:function(){
+              return $scope;
+            }
           }
-        }
-      });
+        });
+      })
     }
   });
 

http://git-wip-us.apache.org/repos/asf/kylin/blob/64a0a594/webapp/app/js/controllers/models.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/models.js b/webapp/app/js/controllers/models.js
index fb2c6d1..e3ee038 100644
--- a/webapp/app/js/controllers/models.js
+++ b/webapp/app/js/controllers/models.js
@@ -18,7 +18,7 @@
 
 'use strict';
 
-KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location, $window, $modal, MessageService, CubeDescService, CubeService, JobService, UserService, ProjectService, SweetAlert, loadingRequest, $log, modelConfig, ProjectModel, ModelService, MetaModel, modelsManager, cubesManager, TableModel, $animate) {
+KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location, $window, $modal, MessageService, CubeDescService, CubeService, JobService, UserService, ProjectService, SweetAlert, loadingRequest, $log, modelConfig, ProjectModel, ModelService, MetaModel, modelsManager, cubesManager, TableModel, AccessService) {
 
   //tree data
 
@@ -131,21 +131,28 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
     var cubename = [];
     var modelstate=false;
     var i=0;
-    if (model.cubes.length != 0) {
-      angular.forEach(model.cubes,function(cube){
-        if (cube.status=="READY"){
-          modelstate=true;
-          cubename[i] =cube.name;
-          i++;
-        }
-      })
-    }
-    if(modelstate==false){
-      $location.path("/models/edit/"+model.name);
-    }
-    else{
-      SweetAlert.swal('Sorry','This model is still used by '+ cubename.join(','));
-    }
+
+    CubeService.list({modelName:model.name}, function (_cubes) {
+      model.cubes = _cubes;
+
+      if (model.cubes.length != 0) {
+        angular.forEach(model.cubes,function(cube){
+          if (cube.status=="READY"){
+            modelstate=true;
+            cubename[i] =cube.name;
+            i++;
+          }
+        })
+      }
+
+      if(modelstate==false){
+        $location.path("/models/edit/"+model.name);
+      }
+      else{
+        SweetAlert.swal('Sorry','This model is still used by '+ cubename.join(','));
+      }
+    })
+
   };
 
   $scope.cloneModel = function(model){
@@ -176,6 +183,21 @@ KylinApp.controller('ModelsCtrl', function ($scope, $q, $routeParams, $location,
     });
   };
 
+  $scope.listModelAccess = function (model) {
+    if(model.uuid){
+      AccessService.list({type: "DataModelDesc", uuid: model.uuid}, function (accessEntities) {
+        model.accessEntities = accessEntities;
+        try {
+          if (!model.owner) {
+            model.owner = accessEntities[0].sid.principal;
+          }
+        } catch (error) {
+          $log.error("No acl info.");
+        }
+      })
+    }
+  };
+
   var ModelDetailModalCtrl = function ($scope, $location, $modalInstance, scope) {
     modelsManager.selectedModel.visiblePage='metadata';
     $scope.cancel = function () {

http://git-wip-us.apache.org/repos/asf/kylin/blob/64a0a594/webapp/app/js/model/cubeListModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/cubeListModel.js b/webapp/app/js/model/cubeListModel.js
index 13c924c..39853c0 100755
--- a/webapp/app/js/model/cubeListModel.js
+++ b/webapp/app/js/model/cubeListModel.js
@@ -25,10 +25,6 @@ KylinApp.service('CubeList',function(CubeService,$q,AccessService){
         var defer = $q.defer();
         CubeService.list(queryParam, function (_cubes) {
             angular.forEach(_cubes, function (cube, index) {
-                AccessService.list({type: "CubeInstance", uuid: cube.uuid}, function (accessEntities) {
-                    cube.accessEntities = accessEntities;
-                });
-
                 if(cube.name){
                     if (cube.segments && cube.segments.length > 0) {
                         for(var i= cube.segments.length-1;i>=0;i--){

http://git-wip-us.apache.org/repos/asf/kylin/blob/64a0a594/webapp/app/js/model/modelsManager.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/modelsManager.js b/webapp/app/js/model/modelsManager.js
index c104405..faa8d39 100644
--- a/webapp/app/js/model/modelsManager.js
+++ b/webapp/app/js/model/modelsManager.js
@@ -25,56 +25,22 @@ KylinApp.service('modelsManager',function(ModelService,CubeService,$q,AccessServ
     this.loading = false;
     this.selectedModel={};
 
-    this.cubeModel={};
-    this.cubeSelected = false;
-
-    //list models and complemete cube,access info
+    //list models
     this.list = function(queryParam){
 
         _this.loading = true;
         var defer = $q.defer();
-        var cubeDetail = [];
-        var modelPermission = [];
         ModelService.list(queryParam, function (_models) {
-            //_this.removeAll();
 
             angular.forEach(_models, function (model, index) {
-                $log.info("Add model permission info");
-                if(model.uuid){
-                  modelPermission.push(
-                  AccessService.list({type: "DataModelDesc", uuid: model.uuid}, function (accessEntities) {
-                    model.accessEntities = accessEntities;
-                    try{
-                      if(!model.owner){
-                          model.owner = accessEntities[0].sid.principal;
-                      }
-                    } catch(error){
-                      $log.error("No acl info.");
-                    }
-
-                  }).$promise
-                  )
-                }
-
-                $log.info("Add cube info to model ,not detail info");
-                cubeDetail.push(
-                    CubeService.list({modelName:model.name}, function (_cubes) {
-                    model.cubes = _cubes;
-                    }).$promise
-                );
-
               _this.modelNameList.push(model.name);
-
-                model.project = ProjectModel.getProjectByCubeModel(model.name);
+              model.project = ProjectModel.getProjectByCubeModel(model.name);
             });
-            $q.all(cubeDetail,modelPermission).then(
-                function(result){
-                    _models = _.filter(_models,function(models){return models.name!=undefined});
-                    _this.models = _models;
-                    _this.loading = false;
-                    defer.resolve(_this.models);
-                }
-            );
+
+            _models = _.filter(_models,function(models){return models.name!=undefined});
+            _this.models = _models;
+            _this.loading = false;
+
         },function(){
             defer.reject("Failed to load models");
         });
@@ -127,5 +93,4 @@ KylinApp.service('modelsManager',function(ModelService,CubeService,$q,AccessServ
         return defer.promise;
     };
 
-
 });

http://git-wip-us.apache.org/repos/asf/kylin/blob/64a0a594/webapp/app/partials/cubes/cubes.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/cubes/cubes.html b/webapp/app/partials/cubes/cubes.html
index 0187523..4be7ecd 100644
--- a/webapp/app/partials/cubes/cubes.html
+++ b/webapp/app/partials/cubes/cubes.html
@@ -54,7 +54,6 @@
             </th>
             <th>Actions</th>
             <th ng-if="userService.hasRole('ROLE_ADMIN')">Admins</th>
-            <th>Streaming</th>
         </tr>
         </thead>
         <!--Body-->
@@ -83,12 +82,12 @@
             <td>{{ cube.owner}}</td>
             <td>{{ cube.create_time_utc | utcToConfigTimeZone}}</td>
             <td>
-                <div ng-click="$event.stopPropagation();" class="btn-group" ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)">
+                <div ng-click="$event.stopPropagation();" class="btn-group">
                     <button type="button" class="btn btn-default btn-xs dropdown-toggle"
                             data-toggle="dropdown" ng-click="listAccess(cube, 'CubeInstance')">
                         Action <span class="ace-icon fa fa-caret-down icon-on-right"></span>
                     </button>
-                    <ul class="dropdown-menu" role="menu">
+                    <ul ng-if="userService.hasRole('ROLE_ADMIN') || hasPermission(cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask)" class="dropdown-menu" role="menu">
                         <li ng-if="cube.status!='READY' && userService.hasRole('ROLE_ADMIN') ">
                             <a ng-click="dropCube(cube)" tooltip="Drop the cube, related jobs and data permanently.">Drop</a></li>
                         <li ng-if="(userService.hasRole('ROLE_ADMIN') || hasPermission(cube, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask))">
@@ -108,20 +107,17 @@
                     N/A
                 </span>
             </td>
-            <td ng-if="userService.hasRole('ROLE_ADMIN')">
+            <td>
                 <div ng-click="$event.stopPropagation();" class="btn-group">
                     <button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown" ng-click="listAccess(cube, 'CubeInstance')">
                         Action <span class="ace-icon fa fa-caret-down icon-on-right"></span>
                     </button>
-                    <ul class="dropdown-menu" role="menu">
+                    <ul class="dropdown-menu" role="menu" ng-if="userService.hasRole('ROLE_ADMIN')">
                         <li ng-if="cube.status!='READY'"><a href="cubes/edit/{{cube.name}}/descriptionjson">Edit CubeDesc</a></li>
                         <li><a href="cubes/view/{{cube.name}}/instancejson">View Cube</a></li>
                     </ul>
                 </div>
             </td>
-            <td>
-              <label class="badge" ng-class="{'label-info':cube.streaming==true}" style="cursor:pointer;">{{cube.streaming}}</label>
-            </td>
         </tr>
         <tr ng-show="cube.showDetail">
             <td colspan="10" style="padding: 10px 30px 10px 30px;">

http://git-wip-us.apache.org/repos/asf/kylin/blob/64a0a594/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 530139e..944d2dc 100644
--- a/webapp/app/partials/models/models_tree.html
+++ b/webapp/app/partials/models/models_tree.html
@@ -41,15 +41,23 @@
   <div>
     <h3 class="text-info">Models</h3>
   </div>
+
     <div style="width:100%; height:{{window}}px; overflow:auto;margin-top: 20px;" class="cube_model_trees">
 
         <ul class="list-group models-tree">
           <li class="list-group-item" ng-repeat="model in modelsManager.models">
 
-            <div class="pull-right" showonhoverparent style="display:none;">
-              <a ng-click="editModel(model)"  title="Edit Model" style="cursor:pointer;margin-right: 8px;" ng-if="(userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask))"><span class="fa fa-pencil fa-lg fa-fw"></span></a>
-              <a ng-click="cloneModel(model)" title="Clone Model"  style="cursor:pointer;margin-right: 8px;" ng-if="(userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask))"><span class="fa fa-copy fa-lg fa-fw"></span></a>
-              <a ng-click="dropModel(model)" title="Drop Model"  style="cursor:pointer;margin-right: 8px;" ng-if="(userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask))"><span class="fa fa-trash-o fa-lg fa-fw"></span></a>
+            <div class="pull-right" showonhoverparent style="display:none;" >
+              <div ng-click="$event.stopPropagation();" class="btn-group">
+                <button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown" ng-click="listModelAccess(model)">
+                  Action <span class="ace-icon fa fa-caret-down icon-on-right"></span>
+                </button>
+                <ul class="dropdown-menu" role="menu" ng-if="(userService.hasRole('ROLE_ADMIN') || hasPermission(model, permissions.ADMINISTRATION.mask, permissions.MANAGEMENT.mask, permissions.OPERATION.mask))">
+                  <li><a ng-click="editModel(model)"  title="Edit Model" style="cursor:pointer;margin-right: 8px;" >Edit</a></li>
+                  <li><a ng-click="cloneModel(model)" title="Clone Model"  style="cursor:pointer;margin-right: 8px;" >Clone </a></li>
+                  <li><a ng-click="dropModel(model)" title="Drop Model"  style="cursor:pointer;margin-right: 8px;">Drop</a></li>
+                </ul>
+              </div>
             </div>
             <span class="strong"><a style="cursor: pointer;word-break:break-all;" ng-click="openModal(model)">{{model.name}}</a></span>
 


[2/2] kylin git commit: KYLIN-2287 minor, UI enhancement

Posted by zh...@apache.org.
KYLIN-2287 minor, UI enhancement


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

Branch: refs/heads/master
Commit: c72e2320238edeb2e7279dc4dc152493837e8843
Parents: 64a0a59
Author: zhongjian <ji...@163.com>
Authored: Tue Dec 20 15:43:12 2016 +0800
Committer: zhongjian <ji...@163.com>
Committed: Tue Dec 20 15:43:12 2016 +0800

----------------------------------------------------------------------
 webapp/app/less/app.less | 8 ++++++++
 1 file changed, 8 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kylin/blob/c72e2320/webapp/app/less/app.less
----------------------------------------------------------------------
diff --git a/webapp/app/less/app.less b/webapp/app/less/app.less
index 5ef5297..85ad937 100644
--- a/webapp/app/less/app.less
+++ b/webapp/app/less/app.less
@@ -72,6 +72,14 @@ body {
   min-width: 110px
 }
 
+.cube_model_trees .dropdown-menu{
+  min-width: 60px;
+}
+
+.cube_model_trees a{
+  margin-right:0px !important;
+}
+
 .login {
   position: fixed;
   width: 325px;