This is an automated email from the ASF dual-hosted git repository.
boblu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kylin.git
The following commit(s) were added to refs/heads/master by this push:
new 10587a6 KYLIN-3599 Bulk Add Measures
10587a6 is described below
commit 10587a65fe0552179a5c8a6e1151686ce1c8a135
Author: liapan <[email protected]>
AuthorDate: Thu Sep 27 18:26:38 2018 +0800
KYLIN-3599 Bulk Add Measures
---
webapp/app/js/controllers/cubeMeasures.js | 209 ++++++++++++++++++++-----
webapp/app/partials/cubeDesigner/measures.html | 51 ++++++
2 files changed, 222 insertions(+), 38 deletions(-)
diff --git a/webapp/app/js/controllers/cubeMeasures.js
b/webapp/app/js/controllers/cubeMeasures.js
index 6fb82f2..7beb528 100644
--- a/webapp/app/js/controllers/cubeMeasures.js
+++ b/webapp/app/js/controllers/cubeMeasures.js
@@ -383,52 +383,116 @@ KylinApp.controller('CubeMeasuresCtrl', function
($scope, $modal,MetaModel,cubes
}
}
if($scope.newMeasure.function.parameter.type=="column"&&$scope.newMeasure.function.expression!=="COUNT_DISTINCT"){
+ $scope.newMeasure.function.returntype =
$scope.getReturnType($scope.newMeasure.function.parameter.value,
$scope.newMeasure.function.expression);
+ }
+ }
+
+ // Open bulk add modal.
+ $scope.openBulkAddModal = function () {
+
+ $scope.initBulkAddMeasures();
+
+ var modalInstance = $modal.open({
+ templateUrl: 'bulkAddMeasures.html',
+ controller: cubeBulkAddMeasureModalCtrl,
+ backdrop: 'static',
+ scope: $scope
+ });
+ };
- var column = $scope.newMeasure.function.parameter.value;
- if(column&&(typeof column=="string")){
- var colType = $scope.getColumnType(VdmUtil.removeNameSpace(column),
VdmUtil.getNameSpaceAliasName(column)); // $scope.getColumnType defined in
cubeEdit.js
+ $scope.initBulkAddMeasures = function() {
+ // init bulk add measure view model
+ $scope.bulkMeasuresView = {
+ SUM: [],
+ MAX: [],
+ MIN: [],
+ RAW: [],
+ PERCENTILE: []
+ };
+ angular.forEach($scope.getCommonMetricColumns(), function(paramValue) {
+ var measures = _.filter($scope.cubeMetaFrame.measures,
function(measure){ return measure.function.parameter.value == paramValue});
+ for (var expression in $scope.bulkMeasuresView) {
+ var bulkMeasure = {
+ name: expression + '_' + paramValue.split('.')[1],
+ parameter: paramValue,
+ returntype: $scope.getReturnType(paramValue, expression),
+ select: false,
+ force: false
+ };
+
+ if (measures.length) {
+ var measure = _.find(measures, function(measure){ return
measure.function.expression == expression});
+ if (!!measure) {
+ bulkMeasure.name = measure.name;
+ bulkMeasure.force = true;
+ bulkMeasure.select = true;
+ }
+ }
+ $scope.bulkMeasuresView[expression].push(bulkMeasure);
}
- if(colType==""||!colType){
- $scope.newMeasure.function.returntype = "";
- return;
+ });
+
+ // init expression selector
+ $scope.bulkMeasureOptions = {
+ expressionList: []
+ };
+
+ for (var expression in $scope.bulkMeasuresView) {
+ var selectArr = _.filter($scope.bulkMeasuresView[expression],
function(measure){ return measure.select && measure.force});
+ var selectAll = $scope.getCommonMetricColumns().length ==
selectArr.length;
+ var expressionSelect = {
+ expression: expression,
+ selectAll: selectAll,
+ force: selectAll
}
+ $scope.bulkMeasureOptions.expressionList.push(expressionSelect);
+ }
+ $scope.bulkMeasureOptions.currentExpression =
$scope.bulkMeasureOptions.expressionList[0];
+ };
- switch($scope.newMeasure.function.expression){
- case "SUM":
-
if(colType==="tinyint"||colType==="smallint"||colType==="int"||colType==="bigint"||colType==="integer"){
- $scope.newMeasure.function.returntype= 'bigint';
+ $scope.getReturnType = function(parameter, expression) {
+ if(parameter && (typeof parameter=="string")){
+ var colType = $scope.getColumnType(VdmUtil.removeNameSpace(parameter),
VdmUtil.getNameSpaceAliasName(parameter)); // $scope.getColumnType defined in
cubeEdit.js
+ }
+ if(colType == '' || !colType) {
+ return '';
+ }
+
+ switch(expression) {
+ case 'SUM':
+ if(colType === 'tinyint' || colType === 'smallint' || colType ===
'int' || colType === 'bigint' || colType === 'integer') {
+ return 'bigint';
+ } else {
+ if(colType.indexOf('decimal') != -1) {
+ var returnRegex = new
RegExp('(\\w+)(?:\\((\\w+?)(?:\\,(\\w+?))?\\))?')
+ var returnValue = returnRegex.exec(colType)
+ var precision = 19
+ var scale = returnValue[3]
+ return 'decimal(' + precision + ',' + scale + ')';
}else{
- if(colType.indexOf('decimal')!=-1){
- var returnRegex = new
RegExp('(\\w+)(?:\\((\\w+?)(?:\\,(\\w+?))?\\))?')
- var returnValue = returnRegex.exec(colType)
- var precision = 19
- var scale = returnValue[3]
- $scope.newMeasure.function.returntype= 'decimal(' + precision +
',' + scale + ')';
- }else{
- $scope.newMeasure.function.returntype= colType;
- }
+ return colType;
}
- break;
- case "MIN":
- case "MAX":
- $scope.newMeasure.function.returntype = colType;
- break;
- case "RAW":
- $scope.newMeasure.function.returntype = "raw";
- break;
- case "COUNT":
- $scope.newMeasure.function.returntype = "bigint";
- break;
- case "PERCENTILE":
- $scope.newMeasure.function.returntype = "percentile(100)";
- break;
- default:
- $scope.newMeasure.function.returntype = "";
- break;
- }
+ }
+ break;
+ case 'MIN':
+ case 'MAX':
+ return colType;
+ break;
+ case 'RAW':
+ return 'raw';
+ break;
+ case 'COUNT':
+ return 'bigint';
+ break;
+ case 'PERCENTILE':
+ return 'percentile(100)';
+ break;
+ default:
+ return '';
+ break;
}
- }
+ };
if ($scope.state.mode == 'edit') {
$scope.$on('$destroy', function () {
@@ -486,3 +550,72 @@ var NextParameterModalCtrl = function ($scope,
scope,para,$modalInstance,cubeCon
}
}
+
+var cubeBulkAddMeasureModalCtrl = function($scope, $modalInstance, SweetAlert)
{
+ $scope.cancel = function () {
+ $modalInstance.dismiss('cancel');
+ };
+
+ $scope.saveBulkMeasures = function () {
+ $scope.bulkMeasures = [];
+ // validation
+ loopExp:
+ for (var expression in $scope.bulkMeasuresView) {
+ loopMeasureView:
+ for (var measureView of $scope.bulkMeasuresView[expression]) {
+ if (!measureView.force) {
+ // validation
+ var measureExisted = _.find($scope.cubeMetaFrame.measures,
function(measure){ return measure.function.parameter.value ==
measureView.parameter && measure.function.expression ==
measureView.expression});
+ if (!!measureExisted) {
+ $scope.bulkMeasures = [];
+ var errMsg = 'Duplicate measure for ' + measureView.name + '
and ' + measureExisted.name + '.';
+ break loopExp;
+ }
+ if (measureView.select) {
+ var measure = {
+ name: measureView.name,
+ function: {
+ expression: expression,
+ returntype: measureView.returntype,
+ parameter: {
+ type: 'column',
+ value: measureView.parameter
+ }
+ }
+ };
+ $scope.bulkMeasures.push(measure);
+ }
+ }
+ }
+ }
+ if (!!errMsg) {
+ SweetAlert.swal('', errMsg, 'warning');
+ } else {
+ $scope.cubeMetaFrame.measures =
$scope.cubeMetaFrame.measures.concat($scope.bulkMeasures);
+ $modalInstance.close();
+ }
+ };
+
+ $scope.selectAll = function() {
+
angular.forEach($scope.bulkMeasuresView[$scope.bulkMeasureOptions.currentExpression.expression],
function(measure) {
+ if (!measure.force) {
+ measure.select = $scope.bulkMeasureOptions.currentExpression.selectAll;
+ }
+ });
+ };
+
+ $scope.measureChange = function(measureSelect) {
+ if ($scope.bulkMeasureOptions.currentExpression.selectAll) {
+ if (!measureSelect) {
+ $scope.bulkMeasureOptions.currentExpression.selectAll = false;
+ }
+ } else {
+ for(var measureView of
$scope.bulkMeasuresView[$scope.bulkMeasureOptions.currentExpression.expression])
{
+ if (!measureView.select) {
+ return;
+ }
+ }
+ $scope.bulkMeasureOptions.currentExpression.selectAll = true;
+ }
+ }
+}
diff --git a/webapp/app/partials/cubeDesigner/measures.html
b/webapp/app/partials/cubeDesigner/measures.html
index 848831c..482e17f 100755
--- a/webapp/app/partials/cubeDesigner/measures.html
+++ b/webapp/app/partials/cubeDesigner/measures.html
@@ -20,6 +20,13 @@
<div ng-controller="CubeMeasuresCtrl">
<ng-form name="forms.cube_measure_form">
<div class="dataTables_wrapper form-inline no-footer"
ng-if="cubeMetaFrame.measures.length > 0">
+ <div class="row">
+ <div class="col-xs-6" ng-if="state.mode=='edit'">
+ <button type="button" class="btn btn-default"
ng-disabled="!metaModel.model.fact_table.length||instance.status=='READY'"
ng-click="openBulkAddModal()" >
+ <i class="fa fa-building-o"></i> Bulk Add Measures
+ </button>
+ </div>
+ </div>
<table class="table table-striped table-hover">
<thead>
<tr>
@@ -341,6 +348,50 @@
</ng-form>
</div>
+<script type="text/ng-template" id="bulkAddMeasures.html">
+ <ng-form name="bulk_add_mes_form">
+ <div class="modal-header large-popover">
+ <h4 class="box-title lighter">Bulk Add Measures</h4>
+ <div class="row">
+ <div class="col-xs-12 col-sm-5 btn-group" >
+ <button type="button" class="btn btn-primary"
ng-repeat="expressionOpt in bulkMeasureOptions.expressionList"
ng-model="bulkMeasureOptions.currentExpression"
btn-radio="expressionOpt">{{expressionOpt.expression}}</button>
+ </div>
+ </div>
+ </div>
+ <div class="modal-body">
+ <table class="table table-striped table-hover">
+ <thead>
+ <tr>
+ <th> <input type="checkbox"
ng-model="bulkMeasureOptions.currentExpression.selectAll"
ng-change="selectAll()"
ng-disabled="bulkMeasureOptions.currentExpression.force" /></th>
+ <th>Name</th>
+ <th>Parameters</th>
+ <th>Return Type</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr ng-repeat="measure in
bulkMeasuresView[bulkMeasureOptions.currentExpression.expression] track by
$index">
+ <td>
+ <input type="checkbox" ng-model="measure.select"
ng-disabled="measure.force" ng-change="measureChange()"/>
+ </td>
+ <td>
+ <input type="text" ng-model="measure.name"
ng-disabled="measure.force" style="width:90%;">
+ </td>
+ <td>
+ <span>{{measure.parameter}}</span>
+ </td>
+ <td>
+ <span>{{measure.returntype}}</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <div class="modal-footer">
+ <button class="btn btn-sm btn-info"
ng-disabled="bulk_add_mes_form.$invalid"
ng-click="saveBulkMeasures()">OK</button>
+ <button class="btn btn-link" ng-click="cancel()">Cancel</button>
+ </div>
+ </ng-form>
+</script>
<script type="text/ng-template" id="expressionTip.html">
<p>All cubes have to contain one measure for Count(1), suggest use "_Count_"
as name (Has been generated automatically)</p>