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:54 UTC
[25/52] [abbrv] incubator-kylin git commit: new model GUI
new model GUI
Project: http://git-wip-us.apache.org/repos/asf/incubator-kylin/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-kylin/commit/a2f4d320
Tree: http://git-wip-us.apache.org/repos/asf/incubator-kylin/tree/a2f4d320
Diff: http://git-wip-us.apache.org/repos/asf/incubator-kylin/diff/a2f4d320
Branch: refs/heads/0.8.0
Commit: a2f4d320b6752333d0a7dafce064101943a7b757
Parents: 6fed6cb
Author: jiazhong <ji...@ebay.com>
Authored: Tue Mar 17 18:10:37 2015 +0800
Committer: honma <ho...@ebay.com>
Committed: Fri May 15 11:36:27 2015 +0800
----------------------------------------------------------------------
.../apache/kylin/common/util/StringUtil.java | 8 +-
.../apache/kylin/metadata/MetadataManager.java | 30 +-
.../kylin/metadata/project/ProjectInstance.java | 36 +-
.../kylin/metadata/project/ProjectManager.java | 43 ++-
.../kylin/rest/controller/ModelController.java | 2 +-
.../apache/kylin/rest/service/ModelService.java | 18 +-
.../apache/kylin/rest/service/QueryService.java | 16 +-
webapp/app/js/controllers/cube.js | 4 +-
webapp/app/js/controllers/cubeModel.js | 4 +-
webapp/app/js/controllers/modelDimensions.js | 370 +------------------
webapp/app/js/controllers/modelEdit.js | 87 +++--
webapp/app/js/controllers/modelSchema.js | 66 +---
webapp/app/js/controllers/projectMeta.js | 2 -
webapp/app/js/model/metaModel.js | 100 ++---
.../modelDesigner/conditions_settings.html | 127 +++++++
.../app/partials/modelDesigner/incremental.html | 94 -----
.../modelDesigner/model_dimensions.html | 339 +++--------------
.../app/partials/modelDesigner/model_info.html | 6 +-
.../partials/modelDesigner/model_measures.html | 156 +-------
webapp/app/partials/models/model_edit.html | 3 +-
webapp/app/partials/models/model_schema.html | 12 +-
21 files changed, 455 insertions(+), 1068 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/common/src/main/java/org/apache/kylin/common/util/StringUtil.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/kylin/common/util/StringUtil.java b/common/src/main/java/org/apache/kylin/common/util/StringUtil.java
index 2d7b170..f4aed14 100644
--- a/common/src/main/java/org/apache/kylin/common/util/StringUtil.java
+++ b/common/src/main/java/org/apache/kylin/common/util/StringUtil.java
@@ -50,9 +50,11 @@ public class StringUtil {
}
public static void toUpperCaseArray(String[] source, String[] target) {
- for (int i = 0; i < source.length; i++) {
- if (source[i] != null) {
- target[i] = source[i].toUpperCase();
+ if(source!=null) {
+ for (int i = 0; i < source.length; i++) {
+ if (source[i] != null) {
+ target[i] = source[i].toUpperCase();
+ }
}
}
}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java b/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
index 9d489e2..ea03933 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/MetadataManager.java
@@ -27,6 +27,8 @@ import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.kylin.metadata.model.TableDesc;
+import org.apache.kylin.metadata.project.ProjectInstance;
+import org.apache.kylin.metadata.project.ProjectManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -253,7 +255,6 @@ public class MetadataManager {
ResourceStore store = getStore();
TableDesc t = store.getResource(path, TableDesc.class, TABLE_SERIALIZER);
if (t == null) {
- logger.error("Didn't load table at " + path);
return null;
}
t.init();
@@ -283,7 +284,24 @@ public class MetadataManager {
}
public List<DataModelDesc> getModels() {
- return new ArrayList<DataModelDesc>(dataModelDescMap.values());
+ return new ArrayList<>(dataModelDescMap.values());
+ }
+
+ public List<DataModelDesc> getModels(String projectName){
+ ProjectInstance projectInstance = ProjectManager.getInstance(config).getProject(projectName);
+ HashSet<DataModelDesc> ret = new HashSet<>();
+ if (projectInstance != null) {
+ for (String modelName : projectInstance.getModels()) {
+ DataModelDesc model = getDataModelDesc(modelName);
+ if (null != model) {
+ ret.add(model);
+ } else {
+ logger.error("Failed to load model" + modelName);
+ }
+ }
+ }
+
+ return new ArrayList<>(ret);
}
@@ -322,12 +340,12 @@ public class MetadataManager {
}
}
- public DataModelDesc createDataModelDesc(DataModelDesc dataModelDesc) throws IOException {
- String name = dataModelDesc.getName();
+ public DataModelDesc createDataModelDesc(DataModelDesc desc,String projectName,String owner) throws IOException {
+ String name = desc.getName();
if (dataModelDescMap.containsKey(name))
throw new IllegalArgumentException("DataModelDesc '" + name + "' already exists");
-
- return saveDataModelDesc(dataModelDesc);
+ ProjectManager.getInstance(config).updateModelToProject(name,projectName,owner);
+ return saveDataModelDesc(desc);
}
public DataModelDesc updateDataModelDesc(DataModelDesc desc) throws IOException {
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java b/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
index 096d2ac..387f735 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectInstance.java
@@ -68,6 +68,9 @@ public class ProjectInstance extends RootPersistentEntity {
@JsonProperty("realizations")
private List<RealizationEntry> realizationEntries;
+ @JsonProperty("models")
+ private List<String> models;
+
public String getResourcePath() {
return concatResourcePath(name);
}
@@ -83,7 +86,7 @@ public class ProjectInstance extends RootPersistentEntity {
return project.toUpperCase();
}
- public static ProjectInstance create(String name, String owner, String description, List<RealizationEntry> realizationEntries) {
+ public static ProjectInstance create(String name, String owner, String description, List<RealizationEntry> realizationEntries,List<String> models) {
ProjectInstance projectInstance = new ProjectInstance();
projectInstance.updateRandomUuid();
@@ -96,7 +99,10 @@ public class ProjectInstance extends RootPersistentEntity {
projectInstance.setRealizationEntries(realizationEntries);
else
projectInstance.setRealizationEntries(Lists.<RealizationEntry> newArrayList());
-
+ if (models != null)
+ projectInstance.setModels(models);
+ else
+ projectInstance.setModels(new ArrayList<String>());
return projectInstance;
}
@@ -231,6 +237,32 @@ public class ProjectInstance extends RootPersistentEntity {
this.realizationEntries = entries;
}
+ public List<String> getModels() {
+ return models;
+ }
+
+ public boolean containsModel(String modelName) {
+ modelName = modelName.toUpperCase();
+ return models!=null&&models.contains(modelName);
+ }
+
+ public void setModels(List<String> models) { this.models = models; }
+
+ public void addModel(String modelName) {
+ modelName = modelName.toUpperCase();
+ if(this.getModels()==null){
+ this.setModels(new ArrayList<String>());
+ }
+ this.getModels().add(modelName);
+ }
+
+ public void removeModel(String modelName){
+ modelName = modelName.toUpperCase();
+ if(this.getModels()!=null) {
+ this.getModels().remove(modelName);
+ }
+ }
+
public void init() {
if (name == null)
name = ProjectInstance.DEFAULT_PROJECT_NAME;
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
----------------------------------------------------------------------
diff --git a/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java b/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
index 33d0867..fb2d298 100644
--- a/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
+++ b/metadata/src/main/java/org/apache/kylin/metadata/project/ProjectManager.java
@@ -164,7 +164,7 @@ public class ProjectManager {
ProjectInstance currentProject = getProject(projectName);
if (currentProject == null) {
- currentProject = ProjectInstance.create(projectName, owner, description, null);
+ currentProject = ProjectInstance.create(projectName, owner, description, null,null);
} else {
throw new IllegalStateException("The project named " + projectName + "already exists");
}
@@ -220,6 +220,36 @@ public class ProjectManager {
}
}
+ public boolean isModelInProject(String projectName, String modelName) {
+ return this.getProject(projectName).containsModel(modelName);
+ }
+
+ public ProjectInstance updateModelToProject(String modelName, String newProjectName, String owner) throws IOException {
+ removeModelFromProjects(modelName);
+
+ return addModelToProject(modelName, newProjectName, owner);
+ }
+
+ public void removeModelFromProjects(String modelName) throws IOException {
+ for (ProjectInstance projectInstance : findProjects(modelName)) {
+ projectInstance.removeModel(modelName);
+
+ saveResource(projectInstance);
+ }
+ }
+
+ private ProjectInstance addModelToProject(String modelName, String project, String user) throws IOException {
+ String newProjectName = ProjectInstance.getNormalizedProjectName(project);
+ ProjectInstance newProject = getProject(newProjectName);
+ if (newProject == null) {
+ newProject = this.createProject(newProjectName, user, "This is a project automatically added when adding model " + modelName);
+ }
+ newProject.addModel(modelName);
+ saveResource(newProject);
+
+ return newProject;
+ }
+
public ProjectInstance moveRealizationToProject(RealizationType type, String realizationName, String newProjectName, String owner) throws IOException {
removeRealizationsFromProjects(type, realizationName);
return addRealizationToProject(type, realizationName, newProjectName, owner);
@@ -288,6 +318,17 @@ public class ProjectManager {
return result;
}
+ private List<ProjectInstance> findProjects(String modelName) {
+ List<ProjectInstance> projects = new ArrayList<ProjectInstance>();
+ for (ProjectInstance projectInstance : projectMap.values()) {
+ if (projectInstance.containsModel(modelName)) {
+ projects.add(projectInstance);
+ }
+ }
+
+ return projects;
+ }
+
public List<TableDesc> listDefinedTables(String project) throws IOException {
return l2Cache.listDefinedTables(norm(project));
}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
index 97a5d32..ce53474 100644
--- a/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
+++ b/server/src/main/java/org/apache/kylin/rest/controller/ModelController.java
@@ -123,7 +123,7 @@ public class ModelController extends BasicController {
String descData = JsonUtil.writeValueAsIndentString(modelDesc);
modelRequest.setModelDescData(descData);
-
+ modelRequest.setSuccessful(true);
return modelRequest;
}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
index 093efe3..e423c37 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/ModelService.java
@@ -19,7 +19,6 @@
package org.apache.kylin.rest.service;
-import org.apache.kylin.job.exception.JobException;
import org.apache.kylin.metadata.model.DataModelDesc;
import org.apache.kylin.metadata.project.ProjectInstance;
import org.apache.kylin.rest.constant.Constant;
@@ -29,10 +28,10 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import java.io.IOException;
-import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -56,9 +55,8 @@ public class ModelService extends BasicService {
if (null == project) {
models = getMetadataManager().getModels();
} else {
- //TO-DO
-// models = listAllModels(projectName);
- models=Collections.emptyList();
+ models = getMetadataManager().getModels(projectName);
+ project.getModels();
}
List<DataModelDesc> filterModels = new ArrayList();
@@ -97,9 +95,10 @@ public class ModelService extends BasicService {
throw new InternalErrorException("The model named " + desc.getName() + " already exists");
}
DataModelDesc createdDesc = null;
- createdDesc = getMetadataManager().createDataModelDesc(desc);
-// ProjectInstance project = getProjectManager().getProject(projectName);
-// accessService.inherit(createdDesc, project);
+ String owner = SecurityContextHolder.getContext().getAuthentication().getName();
+ createdDesc = getMetadataManager().createDataModelDesc(desc,projectName,owner);
+ ProjectInstance project = getProjectManager().getProject(projectName);
+ accessService.inherit(desc, project);
return createdDesc;
}
@@ -108,7 +107,8 @@ public class ModelService extends BasicService {
public DataModelDesc updateModelAndDesc(DataModelDesc desc, String newProjectName) throws IOException {
DataModelDesc existingModel = getMetadataManager().getDataModelDesc(desc.getName());
if (existingModel == null) {
- getMetadataManager().createDataModelDesc(desc);
+ String owner = SecurityContextHolder.getContext().getAuthentication().getName();
+ getMetadataManager().createDataModelDesc(desc,newProjectName,owner);
} else {
getMetadataManager().updateDataModelDesc(desc);
}
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/server/src/main/java/org/apache/kylin/rest/service/QueryService.java
----------------------------------------------------------------------
diff --git a/server/src/main/java/org/apache/kylin/rest/service/QueryService.java b/server/src/main/java/org/apache/kylin/rest/service/QueryService.java
index 027202d..8f81d2d 100644
--- a/server/src/main/java/org/apache/kylin/rest/service/QueryService.java
+++ b/server/src/main/java/org/apache/kylin/rest/service/QueryService.java
@@ -28,16 +28,7 @@ import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import javax.sql.DataSource;
@@ -60,6 +51,7 @@ import org.apache.kylin.rest.request.SQLRequest;
import org.apache.kylin.rest.response.SQLResponse;
import org.apache.kylin.rest.util.QueryUtil;
import org.apache.kylin.rest.util.Serializer;
+import org.h2.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
@@ -280,7 +272,9 @@ public class QueryService extends BasicService {
Connection conn = null;
ResultSet columnMeta = null;
List<TableMeta> tableMetas = null;
-
+ if(StringUtils.isNullOrEmpty(project)){
+ return Collections.emptyList();
+ }
try {
DataSource dataSource = getOLAPDataSource(project);
conn = dataSource.getConnection();
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/js/controllers/cube.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cube.js b/webapp/app/js/controllers/cube.js
index 607706d..2765a45 100755
--- a/webapp/app/js/controllers/cube.js
+++ b/webapp/app/js/controllers/cube.js
@@ -18,12 +18,12 @@
'use strict';
-KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService, CubeService, TableService, CubeGraphService, UserService,SweetAlert) {
+KylinApp.controller('CubeCtrl', function ($scope, AccessService, MessageService, CubeService, TableService, GraphService, UserService,SweetAlert) {
$scope.newAccess = null;
$scope.state = {jsonEdit: false};
$scope.buildGraph = function (cube) {
- CubeGraphService.buildTree(cube);
+ GraphService.buildTree(cube);
};
$scope.getCubeSql = function (cube) {
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/js/controllers/cubeModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/cubeModel.js b/webapp/app/js/controllers/cubeModel.js
index fc2cca8..cfe0f1c 100644
--- a/webapp/app/js/controllers/cubeModel.js
+++ b/webapp/app/js/controllers/cubeModel.js
@@ -18,13 +18,13 @@
'use strict';
-KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,ModelService,MetaModel,SweetAlert,CubeGraphService,$log) {
+KylinApp.controller('CubeModelCtrl', function ($scope, $modal,cubeConfig,ModelService,MetaModel,SweetAlert,GraphService,$log) {
//copy model for show Json in model tab list
$scope.modelJson = angular.copy($scope.model);
$scope.buildGraph = function (model) {
- CubeGraphService.buildTree(model);
+ GraphService.buildTree(model);
};
$scope.cubeConfig = cubeConfig;
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/js/controllers/modelDimensions.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelDimensions.js b/webapp/app/js/controllers/modelDimensions.js
index aa197e6..c89e6a6 100644
--- a/webapp/app/js/controllers/modelDimensions.js
+++ b/webapp/app/js/controllers/modelDimensions.js
@@ -28,375 +28,45 @@ KylinApp.controller('ModelDimensionsCtrl', function ($scope, $modal,MetaModel) {
// Available tables cache: 1st is the fact table, next are lookup tables.
$scope.availableTables = [];
-
-
- /**
- * Helper func to get columns that dimensions based on, three cases:
- * 1. normal dimension: column array.
- * 2. hierarchy dimension: column array, the array index is the hierarchy level.
- * 3. derived dimension: derived columns array.
- * TODO new cube schema change
- */
- var dimCols = function (dim) {
- var referredCols = [];
-
- // Case 3.
- if (dim.derived && dim.derived.length) {
- referredCols = referredCols.concat(dim.derived);
- }
-
- // Case 2.
- if (dim.hierarchy && dim.column.length) {
- referredCols = referredCols.concat(dim.column);
- }
-
- // Case 1.
- if (!dim.derived && !dim.hierarchy) {
- referredCols.push(dim.column);
- }
-
- return referredCols;
- };
+ $scope.dimensions=[];
// Dump available columns plus column table name, whether is from lookup table.
$scope.initColumns = function () {
var factTable = $scope.model.fact_table;
- // At first dump the columns of fact table.
- var cols = $scope.getColumnsByTable(factTable);
-
- // Initialize selected available.
- var factAvailable = {};
- var factSelectAvailable = {};
-
- for (var i = 0; i < cols.length; i++) {
- cols[i].table = factTable;
- cols[i].isLookup = false;
-
- factAvailable[cols[i].name] = cols[i];
-
- // Default not selected and not disabled.
- factSelectAvailable[cols[i].name] = {selected: false, disabled: false};
- }
-
- $scope.availableColumns[factTable] = factAvailable;
- $scope.selectedColumns[factTable] = factSelectAvailable;
- $scope.availableTables.push(factTable);
-
- // Then dump each lookup tables.
+ $scope.availableTables.push($scope.model.fact_table);
var lookups = $scope.model.lookups;
-
for (var j = 0; j < lookups.length; j++) {
- var cols2 = $scope.getColumnsByTable(lookups[j].table);
-
- // Initialize selected available.
- var lookupAvailable = {};
- var lookupSelectAvailable = {};
-
- for (var k = 0; k < cols2.length; k++) {
- cols2[k].table = lookups[j].table;
- cols2[k].isLookup = true;
-
- lookupAvailable[cols2[k].name] = cols2[k];
-
- // Default not selected and not disabled.
- lookupSelectAvailable[cols2[k].name] = {selected: false, disabled: false};
- }
-
- $scope.availableColumns[lookups[j].table] = lookupAvailable;
- $scope.selectedColumns[lookups[j].table] = lookupSelectAvailable;
$scope.availableTables.push(lookups[j].table);
}
- };
- // Check column status: selected or disabled based on current cube dimensions.
- $scope.initColumnStatus = function () {
- angular.forEach($scope.model.dimensions, function (dim) {
- var cols = dimCols(dim);
-
- angular.forEach(cols, function (colName) {
- $scope.selectedColumns[dim.table][colName] = {selected: true, disabled: true};
- });
- });
- };
+// init dimension only when dimen
+// if(!$scope.model.dimensions.length){
- // Initialize data for columns widget in auto-gen when add/edit cube.
- if ($scope.state.mode == 'edit') {
- $scope.initColumns();
- }
+ for(var i = 0;i<$scope.availableTables.length;i++){
+ var tableInUse = _.some($scope.model.dimensions,function(item){
+ return item.table == $scope.availableTables[i];
+ });
- // Initialize params for add/edit dimension.
- $scope.dimState = {
- editing: false,
- editingIndex: -1,
- filter: ''
- };
-
- // Init the dimension, dimension name default as the column key. TODO new cube schema change.
- var Dimension = function (table, selectedCols, dimType) {
- var origin = {name: '', table: table,hierarchy:false,derived:null,column:null};
-
- switch (dimType) {
- case 'normal':
- // Default name as 1st column name.
- if (table && selectedCols.length) {
- origin.name = table + '.' + selectedCols[0];
- }
-
- origin.column = selectedCols;
- break;
-
- case 'derived':
- if (table && selectedCols.length) {
- origin.name = table + '_derived';
- }
-
- origin.derived = selectedCols;
- break;
-
- case 'hierarchy':
- if (table && selectedCols.length) {
- origin.name = table + '_hierarchy';
+ if(!tableInUse){
+ $scope.model.dimensions.push(new Dimension($scope.availableTables[i]));
}
-
- origin.hierarchy = true;
- origin.column = selectedCols;
- break;
- }
-
- return origin;
- };
-
- // Since old schema may be both derived and hierarchy. TODO new cube schema change.
- $scope.getDimType = function (dim) {
- var types = [];
-
- if (dim.derived && dim.derived.length) {
- types.push('derived');
- }
-
- if (dim.hierarchy && dim.column.length) {
- types.push('hierarchy');
- }
-
- if (!types.length) {
- types.push('normal');
- }
-
- return types;
- };
-
- var dimList = $scope.model.dimensions;
-
- // Open add/edit dimension modal.
- $scope.openDimModal = function (dimType) {
- var modalInstance = $modal.open({
- templateUrl: 'addEditDimension.html',
- controller: cubeDimModalCtrl,
- backdrop: 'static',
- scope: $scope,
- resolve: {
- dimType: function () {
- // For old schema compatibility, convert into array here. TODO new cube schema change.
- return angular.isArray(dimType) ? dimType : [dimType];
- }
- }
- });
-
- modalInstance.result.then(function () {
- if (!$scope.dimState.editing) {
- $scope.doneAddDim();
- } else {
- $scope.doneEditDim();
}
+// }
- }, function () {
- $scope.cancelDim();
- });
- };
-
- // Controller for cube dimension add/edit modal.
- var cubeDimModalCtrl = function ($scope, $modalInstance, dimType) {
- $scope.dimType = dimType;
-
- $scope.ok = function () {
- $modalInstance.close();
- };
-
- $scope.cancel = function () {
- $modalInstance.dismiss('cancel');
- };
- };
-
- $scope.addDim = function (dimType) {
- $scope.newDimension = Dimension('', [], dimType);
-
- $scope.openDimModal(dimType);
- };
-
- $scope.editDim = function (dim) {
- $scope.dimState.editingIndex = dimList.indexOf(dim);
- $scope.dimState.editing = true;
-
- // Make a copy of model will be editing.
- $scope.newDimension = angular.copy(dim);
-
- $scope.openDimModal($scope.getDimType(dim));
- };
-
- $scope.doneAddDim = function () {
- // Push new dimension which bound user input data.
- dimList.push(angular.copy($scope.newDimension));
-
- $scope.resetParams();
- };
-
- $scope.doneEditDim = function () {
- // Copy edited model to destination model.
- angular.copy($scope.newDimension, dimList[$scope.dimState.editingIndex]);
-
- $scope.resetParams();
- };
-
- $scope.cancelDim = function () {
- $scope.resetParams();
- };
-
- $scope.removeDim = function (dim) {
- dimList.splice(dimList.indexOf(dim), 1);
- };
-
- $scope.resetParams = function () {
- $scope.dimState.editing = false;
- $scope.dimState.editingIndex = -1;
-
- $scope.newDimension = {};
- };
-
- // Open auto-gen dimension modal.
- $scope.openAutoGenModal = function (dimType) {
- // Init columns status.
- $scope.initColumnStatus();
-
- var modalInstance = $modal.open({
- templateUrl: 'autoGenDimension.html',
- controller: cubeAutoGenDimModalCtrl,
- backdrop: 'static',
- scope: $scope
- });
-
- modalInstance.result.then(function () {
- $scope.autoGenDims();
- }, function () {
- $scope.resetGenDims();
- });
- };
-
- // Controller for cube dimension auto-gen modal.
- var cubeAutoGenDimModalCtrl = function ($scope, $modalInstance) {
- $scope.ok = function () {
- $modalInstance.close();
- };
-
- $scope.cancel = function () {
- $modalInstance.dismiss('cancel');
- };
- };
-
- // Helper func to get the selected status in auto gen.
- $scope.getSelectedCols = function () {
- var selectedCols = {};
-
- angular.forEach($scope.selectedColumns, function (value, table) {
- angular.forEach(value, function (status, colName) {
- if (status.selected && !status.disabled) {
- if (!selectedCols[table]) {
- selectedCols[table] = [];
- }
-
- selectedCols[table].push(colName);
- }
- });
- });
-
- return selectedCols;
- };
-
- // Auto generate dimensions.
- $scope.autoGenDims = function () {
- var selectedCols = $scope.getSelectedCols();
-
- angular.forEach(selectedCols, function (cols, table) {
- if ($scope.model.fact_table == table) {
- // Fact table: for each selected column, create one normal dimension.
- for (var i = 0; i < cols.length; i++) {
- dimList.push(Dimension(table, [cols[i]], 'normal'));
- }
- } else {
- // Per lookup table, create one derived dimension for all its selected columns;
- if (cols.length) {
- dimList.push(Dimension(table, cols, 'derived'));
- }
- }
- });
- };
+ // At first dump the columns of fact table.
+// var cols = $scope.getColumnsByTable(factTable);
- // Just reset the selected status of columns.
- $scope.resetGenDims = function () {
- var selectedCols = $scope.getSelectedCols();
- angular.forEach(selectedCols, function (cols, table) {
- for (var i = 0; i < cols.length; i++) {
- $scope.selectedColumns[table][cols[i]].selected = false;
- }
- });
};
- // Check whether there is column conflicts.
- $scope.dimConflicts = [];
-
- $scope.$watch('cubeMetaFrame.dimensions', function (newVal, oldVal) {
- if (!newVal || !newVal.length) {
- return;
- }
-
- var referredCols = {};
-
- angular.forEach(newVal, function (curDim) {
- var table = curDim.table;
- var cols = dimCols(curDim);
-
- for (var i = 0; i < cols.length; i++) {
- var key = table + '.' + cols[i];
-
- if (!referredCols[key]) {
- referredCols[key] = [];
- }
-
- referredCols[key].push({id: curDim.id, name: curDim.name});
- }
- });
-
- var conflicts = [];
-
- angular.forEach(referredCols, function (dims, key) {
- if (dims.length > 1) {
- // More than 1 dimensions has referred this column.
- var colInfo = key.split('.');
- conflicts.push({table: colInfo[0], column: colInfo[1], dims: dims});
- }
- });
-
- $scope.dimConflicts = conflicts;
- }, true);
-
-
+ var Dimension = function(table){
+ this.table = table;
+ this.columns = [];
+ }
+ // Initialize data for columns widget in auto-gen when add/edit cube.
if ($scope.state.mode == 'edit') {
- $scope.$on('$destroy', function () {
- // $scope.dimensionsAdapter();
- // Emit dimensions edit event in order to re-generate row key.
- $scope.$emit('DimensionsEdited');
- });
- }
+ $scope.initColumns();
+ };
});
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/js/controllers/modelEdit.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelEdit.js b/webapp/app/js/controllers/modelEdit.js
index 2741d2c..38290f7 100644
--- a/webapp/app/js/controllers/modelEdit.js
+++ b/webapp/app/js/controllers/modelEdit.js
@@ -19,8 +19,7 @@
'use strict';
-KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $location, $templateCache, $interpolate, MessageService, TableService, CubeDescService, CubeService, loadingRequest, SweetAlert,$log,cubeConfig,CubeDescModel,ModelDescService,MetaModel,TableModel) {
- $scope.cubeConfig = cubeConfig;
+KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $location, $templateCache, $interpolate, MessageService, TableService, CubeDescService, ModelService, loadingRequest, SweetAlert,$log,cubeConfig,CubeDescModel,ModelDescService,MetaModel,TableModel,ProjectService,ProjectModel) {
//add or edit ?
var absUrl = $location.absUrl();
$scope.modelMode = absUrl.indexOf("/models/add")!=-1?'addNewModel':absUrl.indexOf("/models/edit")!=-1?'editExistModel':'default';
@@ -57,12 +56,16 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
// ~ Define data
$scope.state = {
- "modelSchema": ""
+ "modelSchema": "",
+ mode:'edit',
+ modelName: $scope.routeParams.modelName,
+ project:$scope.projectModel.selectedProject
};
// ~ init
if ($scope.isEdit = !!$routeParams.modelName) {
- ModelDescService.get({model_name: $routeParams.modelName}, function (model) {
+ var modelName = $routeParams.modelName;
+ ModelDescService.get({model_name: modelName}, function (model) {
if (model) {
$scope.model = model;
//use
@@ -74,19 +77,43 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
}
}
});
+ //init project
+ ProjectService.list({}, function (projects) {
+ $scope.projects = projects;
+ if (modelName) {
+ var projName = null;
+ if(ProjectModel.getSelectedProject()){
+ projName=ProjectModel.getSelectedProject();
+ }else{
+ angular.forEach($scope.projects, function (project, index) {
+ angular.forEach(project.models, function (unit, index) {
+ if (!projName && unit === modelName) {
+ projName = project.name;
+ }
+ });
+ });
+ }
- } else {
- $scope.model = MetaModel.createNew();;
- }
+ if(!ProjectModel.getSelectedProject()){
+ ProjectModel.setSelectedProject(projName);
+ TableModel.aceSrcTbLoaded();
+ }
- // ~ public methods
- $scope.aceChanged = function () {
- };
+ $scope.state.project = projName;
+ }
+
+ angular.forEach($scope.projects, function (project, index) {
+ $scope.listAccess(project, 'ProjectInstance');
+ });
+ });
- $scope.aceLoaded = function(){
- };
- $scope.prepareCube = function () {
+ } else {
+ MetaModel.initModel();
+ $scope.model = MetaModel.getMetaModel();
+ }
+
+ $scope.prepareModel = function () {
// generate column family
if ($scope.model.partition_desc.partition_date_column&&($scope.model.partition_desc.partition_date_start|$scope.model.partition_desc.partition_date_start==0)) {
@@ -102,22 +129,22 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
}
$scope.state.modelSchema = angular.toJson($scope.model, true);
- $scope.state.project = $scope.projectModel.selectedProject;
+// $scope.state.project = $scope.projectModel.selectedProject;
};
- $scope.cubeResultTmpl = function (notification) {
+ $scope.modelResultTmpl = function (notification) {
// Get the static notification template.
- var tmpl = notification.type == 'success' ? 'cubeResultSuccess.html' : 'cubeResultError.html';
+ var tmpl = notification.type == 'success' ? 'modelResultSuccess.html' : 'modelResultError.html';
return $interpolate($templateCache.get(tmpl))(notification);
};
$scope.saveModel = function (design_form) {
try {
- angular.fromJson($scope.state.cubeSchema);
+ angular.fromJson($scope.state.modelSchema);
} catch (e) {
- SweetAlert.swal('Oops...', 'Invalid cube json format..', 'error');
+ SweetAlert.swal('Oops...', 'Invalid model json format..', 'error');
return;
}
@@ -134,10 +161,10 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
loadingRequest.show();
if ($scope.isEdit) {
- CubeService.update({}, {modelDescData:$scope.state.modelSchema, modelName: $routeParams.modelName, project: $scope.state.project}, function (request) {
+ ModelService.update({}, {modelDescData:$scope.state.modelSchema, modelName: $routeParams.modelName, project: $scope.state.project}, function (request) {
if (request.successful) {
$scope.state.modelSchema = request.modelSchema;
- MessageService.sendMsg($scope.cubeResultTmpl({'text':'Updated the cube successfully.',type:'success'}), 'success', {}, true, 'top_center');
+ MessageService.sendMsg($scope.modelResultTmpl({'text':'Updated the model successfully.',type:'success'}), 'success', {}, true, 'top_center');
if (design_form) {
design_form.$invalid = true;
@@ -146,7 +173,7 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
$scope.saveModelRollBack();
var message =request.message;
var msg = !!(message) ? message : 'Failed to take action.';
- MessageService.sendMsg($scope.cubeResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
+ MessageService.sendMsg($scope.modelResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
}
//end loading
loadingRequest.hide();
@@ -156,23 +183,23 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
if(e.data&& e.data.exception){
var message =e.data.exception;
var msg = !!(message) ? message : 'Failed to take action.';
- MessageService.sendMsg($scope.cubeResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
+ MessageService.sendMsg($scope.modelResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
} else {
- MessageService.sendMsg($scope.cubeResultTmpl({'text':'Failed to take action.','schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
+ MessageService.sendMsg($scope.modelResultTmpl({'text':'Failed to take action.','schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
}
loadingRequest.hide();
});
} else {
- CubeService.save({}, {cubeDescData: $scope.state.cubeSchema,modelDescData:$scope.state.modelSchema, project: $scope.state.project}, function (request) {
+ ModelService.save({}, {modelDescData:$scope.state.modelSchema, project: $scope.state.project}, function (request) {
if(request.successful) {
$scope.state.modelSchema = request.modelSchema;
- MessageService.sendMsg($scope.cubeResultTmpl({'text':'Created the cube successfully.',type:'success'}), 'success', {}, true, 'top_center');
+ MessageService.sendMsg($scope.modelResultTmpl({'text':'Created the model successfully.',type:'success'}), 'success', {}, true, 'top_center');
} else {
$scope.saveModelRollBack();
var message =request.message;
var msg = !!(message) ? message : 'Failed to take action.';
- MessageService.sendMsg($scope.cubeResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
+ MessageService.sendMsg($scope.modelResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
}
//end loading
@@ -183,9 +210,9 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
if (e.data && e.data.exception) {
var message =e.data.exception;
var msg = !!(message) ? message : 'Failed to take action.';
- MessageService.sendMsg($scope.cubeResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
+ MessageService.sendMsg($scope.modelResultTmpl({'text':msg,'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
} else {
- MessageService.sendMsg($scope.cubeResultTmpl({'text':"Failed to take action.",'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
+ MessageService.sendMsg($scope.modelResultTmpl({'text':"Failed to take action.",'schema':$scope.state.modelSchema}), 'error', {}, true, 'top_center');
}
//end loading
loadingRequest.hide();
@@ -207,6 +234,10 @@ KylinApp.controller('ModelEditCtrl', function ($scope, $q, $routeParams, $locati
}
};
+ $scope.removeTableDimensions = function(tableIndex){
+ $scope.model.dimensions.splice(tableIndex,1);
+ }
+
$scope.$watch('projectModel.selectedProject', function (newValue, oldValue) {
if(!newValue){
return;
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/js/controllers/modelSchema.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/modelSchema.js b/webapp/app/js/controllers/modelSchema.js
index 112507e..198a9a3 100644
--- a/webapp/app/js/controllers/modelSchema.js
+++ b/webapp/app/js/controllers/modelSchema.js
@@ -32,7 +32,7 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
{title: 'Data Model', src: 'partials/modelDesigner/data_model.html', isComplete: false},
{title: 'Dimensions', src: 'partials/modelDesigner/model_dimensions.html', isComplete: false},
{title: 'Measures', src: 'partials/modelDesigner/model_measures.html', isComplete: false},
- {title: 'Refresh Setting', src: 'partials/modelDesigner/incremental.html', isComplete: false}
+ {title: 'Settings', src: 'partials/modelDesigner/conditions_settings.html', isComplete: false}
];
$scope.curStep = $scope.wizardSteps[0];
@@ -58,70 +58,6 @@ KylinApp.controller('ModelSchemaCtrl', function ($scope, QueryService, UserServi
return $scope.userService.hasRole('ROLE_ADMIN') || $scope.hasPermission(project,$scope.permissions.ADMINISTRATION.mask);
};
- $scope.addNewMeasure = function (measure) {
- $scope.newMeasure = (!!measure)? measure:CubeDescModel.createMeasure();
- };
-
- $scope.clearNewMeasure = function () {
- $scope.newMeasure = null;
- };
-
- $scope.saveNewMeasure = function () {
- if ($scope.cubeMetaFrame.measures.indexOf($scope.newMeasure) === -1) {
- $scope.cubeMetaFrame.measures.push($scope.newMeasure);
- }
- $scope.newMeasure = null;
- };
-
- //map right return type for param
- $scope.measureReturnTypeUpdate = function(){
- if($scope.newMeasure.function.expression!=="COUNT_DISTINCT"){
-
- var column = $scope.newMeasure.function.parameter.value;
- var colType = $scope.getColumnType(column, $scope.metaModel.model.fact_table); // $scope.getColumnType defined in cubeEdit.js
-
-
- switch($scope.newMeasure.function.expression){
- case "SUM":
- if(colType==="smallint"||colType==="int"||colType==="bigint"){
- $scope.newMeasure.function.returntype= 'bigint';
- }else{
- $scope.newMeasure.function.returntype= 'decimal';
- }
- break;
- case "MIN":
- case "MAX":
- $scope.newMeasure.function.returntype = colType;
- break;
- case "COUNT":
- $scope.newMeasure.function.returntype = "bigint";
- break;
- default:
- $scope.newMeasure.function.returntype = "";
- break;
- }
- }
- }
-
- $scope.addNewRowkeyColumn = function () {
- $scope.cubeMetaFrame.rowkey.rowkey_columns.push({
- "column": "",
- "length": 0,
- "dictionary": "true",
- "mandatory": false
- });
- };
-
- $scope.addNewAggregationGroup = function () {
- $scope.cubeMetaFrame.rowkey.aggregation_groups.push([]);
- };
-
- $scope.refreshAggregationGroup = function (list, index, aggregation_groups) {
- if (aggregation_groups) {
- list[index] = aggregation_groups;
- }
- };
-
$scope.removeElement = function (arr, element) {
var index = arr.indexOf(element);
if (index > -1) {
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/js/controllers/projectMeta.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/controllers/projectMeta.js b/webapp/app/js/controllers/projectMeta.js
index d1ba98a..aa35d03 100644
--- a/webapp/app/js/controllers/projectMeta.js
+++ b/webapp/app/js/controllers/projectMeta.js
@@ -78,9 +78,7 @@ KylinApp
$scope.$watch('projectModel.selectedProject', function (newValue, oldValue) {
- if(newValue){
$scope.projectMetaLoad();
- }
});
$scope.trimType = function(typeName){
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/js/model/metaModel.js
----------------------------------------------------------------------
diff --git a/webapp/app/js/model/metaModel.js b/webapp/app/js/model/metaModel.js
index 74714d9..28e9f69 100644
--- a/webapp/app/js/model/metaModel.js
+++ b/webapp/app/js/model/metaModel.js
@@ -21,58 +21,74 @@
*/
KylinApp.service('MetaModel',function(){
- var _this = this;
//data model when edit model
- this.name=null;
- this.fact_table=null;
- this.lookups=[];
- this.filter_condition=null;
- this.capacity=null;
- this.dimensions=[];
- this.metrics=[];
- this.partition_desc = {
- "partition_date_column" : '',
- "partition_date_start" : 0,
- "partition_type" : 'APPEND'
+ this.model={
+ name: null,
+ fact_table: null,
+ lookups: [],
+ filter_condition:null,
+ capacity:null,
+ dimensions:[],
+ metrics:[],
+ "partition_desc" : {
+ "partition_date_column" : '',
+ "partition_date_start" : 0,
+ "partition_type" : 'APPEND'
+ },
+ last_modified:0
};
- this.last_modified=0;
+
this.setMetaModel =function(model){
- _this.name = model.name;
- _this.fact_table = model.fact_table;
- _this.lookups =model.lookups;
- _this.filter_condition = model.filter_condition;
- _this.capacity = model.capacity;
- _this.partition_desc = model.partition_desc;
- _this.last_modified = model.last_modified;
- _this.metrics = model.metrics;
- _this.dimensions = model.dimensions;
+ var _model = {};
+ _model.name = model.name;
+ _model.fact_table = model.fact_table;
+ _model.lookups =model.lookups;
+ _model.filter_condition = model.filter_condition;
+ _model.capacity = model.capacity;
+ _model.dimensions = model.dimensions;
+ _model.metrics = model.metrics;
+ _model.partition_desc = model.partition_desc;
+ _model.last_modified = model.last_modified;
+ this.model = _model;
+ };
+
+ this.initModel = function(){
+ this.model = this.createNew();
+ }
+
+ this.getMetaModel = function(){
+ return this.model;
+ };
+
+ this.setFactTable = function(fact_table) {
+ this.model.fact_table =fact_table;
};
this.converDateToGMT = function(){
- if(this.partition_desc&&this.partition_desc.partition_date_start){
- this.partition_desc.partition_date_start+=new Date().getTimezoneOffset()*60000;
+ if(this.model.partition_desc&&this.model.partition_desc.partition_date_start){
+ this.model.partition_desc.partition_date_start+=new Date().getTimezoneOffset()*60000;
}
};
//
this.createNew = function () {
- var metaModel = {
- name: '',
- fact_table: '',
- lookups: [],
- filter_condition:'',
- capacity:'MEDIUM',
- dimensions:[],
- metrics:[],
- "partition_desc" : {
- "partition_date_column" : '',
- "partition_date_start" : 0,
- "partition_type" : 'APPEND'
- },
- last_modified:0
- };
+ var metaModel = {
+ name: '',
+ fact_table: '',
+ lookups: [],
+ filter_condition:'',
+ capacity:'MEDIUM',
+ dimensions:[],
+ metrics:[],
+ "partition_desc" : {
+ "partition_date_column" : '',
+ "partition_date_start" : 0,
+ "partition_type" : 'APPEND'
+ },
+ last_modified:0
+ };
- return metaModel;
- }
-})
+ return metaModel;
+ }
+})
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/partials/modelDesigner/conditions_settings.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/conditions_settings.html b/webapp/app/partials/modelDesigner/conditions_settings.html
new file mode 100644
index 0000000..7994fa1
--- /dev/null
+++ b/webapp/app/partials/modelDesigner/conditions_settings.html
@@ -0,0 +1,127 @@
+<!--
+* 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 ng-controller="CubeRefreshCtrl">
+<div class="row">
+ <div class="col-xs-8">
+
+ <!--Cube Partition Type-->
+ <div class="form-group" ng-hide="true">
+ <div class="row">
+ <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Partition Type</b></label>
+ <div class="col-xs-12 col-sm-6">
+ <select class="form-control"
+ ng-if="state.mode=='edit'"
+ chosen ng-model="model.partition_desc.partition_type"
+ ng-options="ddt as ddt for ddt in cubeConfig.cubePartitionTypes">
+ <option value=""></option>
+ </select>
+ <span ng-if="state.mode=='view'">{{model.partition_desc.partition_type}}</span>
+ </div>
+ </div>
+ </div>
+
+ <!--Partition Column-->
+ <div class="form-group">
+ <div class="row">
+ <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Partition Date Column</b></label>
+ <div class="col-xs-12 col-sm-6">
+
+ <select style="width: 100%" chosen data-placeholder="e.g. DEFAULT.TEST_KYLIN_FACT.CAL_DT"
+ ng-required="model.partition_desc.partition_date_start"
+ ng-model="model.partition_desc.partition_date_column"
+ ng-if="state.mode=='edit'"
+ data-placement=""
+ ng-options="model.fact_table+'.'+columns.name as model.fact_table+'.'+columns.name for columns in getPartitonColumns(model.fact_table)" >
+ <option value="">--Select Partition Column--</option>
+ </select>
+ <p class="text-red" ng-if="state.mode=='edit'">(data format in column should be 'YYYY-MM-DD')</p>
+ <span ng-if="state.mode=='view'">
+ {{!!(model.partition_desc.partition_date_column)?model.partition_desc.partition_date_column: ''}}</span>
+ </div>
+ </div>
+ </div>
+
+ <!--Data Range Start-->
+ <div class="form-group">
+ <div class="row">
+ <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Start Date</b></label>
+ <div class="col-xs-12 col-sm-6">
+ <!--edit model will convert in MetaModel.converDateToGMT-->
+ <input type="text" class="form-control" datepicker-popup="yyyy-MM-dd"
+ ng-model="model.partition_desc.partition_date_start" ng-if="state.mode=='edit'"
+ placeholder="Click to choose start date..." is-open="opened" />
+ <!--vier model will convert use filter-->
+ <span ng-if="state.mode=='view'&&model.partition_desc.partition_date_column">{{(model.partition_desc.partition_date_start)|reverseToGMT0 }}</span>
+ </div>
+ </div>
+ </div>
+
+ <!--Filter Condition-->
+ <div class="form-group">
+ <div class="row">
+ <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Filter</b></label>
+ <div class="col-xs-12 col-sm-6">
+
+ <!--edit mode-->
+ <div class="form-group" ng-if="state.mode=='edit'"
+ style="font-family:'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro'">
+ <label for="filter_condition"
+ style="color: #930f80;"><b>WHERE</b></label>
+ <textarea id="filter_condition" type="text"
+ style="height:150px"
+ class="form-control box-default"
+ placeholder="Please input WHERE clause without typing 'WHERE'"
+ ng-model="model.filter_condition">
+ </textarea>
+ </div>
+
+ <!--view mode-->
+ <div class="form-group row" ng-if="state.mode=='view'"
+ style="font-family:'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro'">
+ <div ng-if="model.filter_condition" class="col-md-11 col-md-offset-1">
+ <p style="color: #930f80;"><b>WHERE</b></p>
+ <span>{{model.filter_condition}}</span>
+ </div>
+ </div>
+
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div class="col-xs-4">
+ <div class="box box-solid">
+ <div class="box-header">
+ <h4 class="box-title">Tips</h4>
+ </div>
+ <div class="box-body">
+ <div class="row">
+ <div class="col-xs-12">
+ <ol class="text-info">
+ <li>Not required,leave as default if this cube always need full build</li>
+ <li>Partition column will select 'date' or 'string' type column from fact table</li>
+ <li>If column selected,please indicate start date to just pull certain data from source</li>
+ </ol>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+</div>
+</div>
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/partials/modelDesigner/incremental.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/incremental.html b/webapp/app/partials/modelDesigner/incremental.html
deleted file mode 100644
index 3238b1c..0000000
--- a/webapp/app/partials/modelDesigner/incremental.html
+++ /dev/null
@@ -1,94 +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 ng-controller="ModelRefreshCtrl">
-<div class="row">
- <div class="col-xs-8">
-
- <div class="form-group" ng-hide="true">
- <div class="row">
- <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Partition Type</b></label>
- <div class="col-xs-12 col-sm-6">
- <select class="form-control"
- ng-if="state.mode=='edit'"
- chosen ng-model="model.partition_desc.partition_type"
- ng-options="ddt as ddt for ddt in cubeConfig.cubePartitionTypes">
- <option value=""></option>
- </select>
- <span ng-if="state.mode=='view'">{{model.partition_desc.partition_type}}</span>
- </div>
- </div>
- </div>
-
- <!--Partition Column-->
- <div class="form-group">
- <div class="row">
- <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Partition Date Column</b></label>
- <div class="col-xs-12 col-sm-6">
-
- <select style="width: 100%" chosen data-placeholder="e.g. DEFAULT.TEST_KYLIN_FACT.CAL_DT"
- ng-required="model.partition_desc.partition_date_start"
- ng-model="model.partition_desc.partition_date_column"
- ng-if="state.mode=='edit'"
- data-placement=""
- ng-options="model.fact_table+'.'+columns.name as model.fact_table+'.'+columns.name for columns in getPartitonColumns(model.fact_table)" >
- <option value="">--Select Partition Column--</option>
- </select>
- <p class="text-red" ng-if="state.mode=='edit'">(data format in column should be 'YYYY-MM-DD')</p>
- <span ng-if="state.mode=='view'">
- {{!!(model.partition_desc.partition_date_column)?model.partition_desc.partition_date_column: ''}}</span>
- </div>
- </div>
- </div>
-
- <!--Data Range Start-->
- <div class="form-group">
- <div class="row">
- <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Start Date</b></label>
- <div class="col-xs-12 col-sm-6">
- <!--edit model will convert in MetaModel.converDateToGMT-->
- <input type="text" class="form-control" datepicker-popup="yyyy-MM-dd"
- ng-model="model.partition_desc.partition_date_start" ng-if="state.mode=='edit'"
- placeholder="Click to choose start date..." is-open="opened" />
- <!--vier model will convert use filter-->
- <span ng-if="state.mode=='view'&&model.partition_desc.partition_date_column">{{(model.partition_desc.partition_date_start)|reverseToGMT0 }}</span>
- </div>
- </div>
- </div>
- </div>
-
- <div class="col-xs-4">
- <div class="box box-solid">
- <div class="box-header">
- <h4 class="box-title">Tips</h4>
- </div>
- <div class="box-body">
- <div class="row">
- <div class="col-xs-12">
- <ol class="text-info">
- <li>Not required,leave as default if cube always need full build</li>
- <li>Partition column will select 'date' or 'string' type column from fact table</li>
- <li>If column selected,please indicate start date to just pull certain data from source</li>
- </ol>
- </div>
- </div>
- </div>
- </div>
- </div>
-</div>
-</div>
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/partials/modelDesigner/model_dimensions.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/model_dimensions.html b/webapp/app/partials/modelDesigner/model_dimensions.html
index 8be67d1..cd529d9 100644
--- a/webapp/app/partials/modelDesigner/model_dimensions.html
+++ b/webapp/app/partials/modelDesigner/model_dimensions.html
@@ -20,24 +20,8 @@
<!-- Dimensions Summary -->
<div class="dataTables_wrapper form-inline no-footer">
- <div class="row">
- <div class="col-xs-6" ng-if="state.mode=='edit'">
- <div class="btn-group">
- <button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">
- <i class="fa fa-plus"></i> Add Dimension <span class="ace-icon fa fa-caret-down icon-on-right"></span>
- </button>
- <ul class="dropdown-menu" role="menu">
- <li><a ng-click="addDim('normal')">Normal</a></li>
- <li><a ng-click="addDim('hierarchy')">Hierarchy</a></li>
- <li><a ng-click="addDim('derived')">Derived</a></li>
- </ul>
- </div>
- <button type="button" class="btn btn-default" ng-disabled="!model.fact_table.length"
- ng-click="openAutoGenModal()">
- <i class="fa fa-building-o"></i> Auto Generator
- </button>
- </div>
- <div class="col-xs-6" ng-if="state.mode!='edit'">
+ <div class="row" ng-if="state.mode=='view'">
+ <div class="col-xs-6">
<b>Dimensions</b>
</div>
<div class="col-xs-6">
@@ -47,15 +31,14 @@
</span>
</div>
</div>
- <table class="table table-striped table-hover" ng-if="model.dimensions.length > 0">
+
+ <!-- VIEW MODE -->
+ <table class="table table-striped table-hover" ng-if="state.mode=='view'&&model.dimensions.length > 0">
<thead>
<tr>
<th>ID</th>
- <th>Name</th>
<th>Table Name</th>
- <th>Type</th>
- <th></th>
- <th ng-if="state.mode=='edit'">Actions</th>
+ <th>Columns</th>
</tr>
</thead>
<tbody class="cube-dimension">
@@ -66,289 +49,55 @@
</td>
<!--Name -->
<td>
- <span>{{dimension.name}}</span>
+ <span>{{dimension.table}}</span>
</td>
<!--Table Name -->
<td>
- <span tooltip="{{dimension.table == model.fact_table ? 'Fact Table' : 'Lookup Table'}}">{{dimension.table}}</span>
+ <span>{{dimension.columns}}</span>
</td>
- <!--Type-->
- <td>
- <span class="label label-primary" ng-repeat="t in getDimType(dimension)">{{t}}</span>
+ </tr>
+ </tbody>
+ </table>
+
+ <div ng-if="state.mode=='edit'" class="form-group model-dimension-edit" style="width: 100%">
+ <h4 style="margin-left:42px">Dimensions</h4>
+ <table style="margin-left:42px; width:92%"
+ ng-if="model.dimensions.length > 0"
+ class="table table-hover list">
+ <tr class="row">
+ <th class="col-xs-1">ID</th>
+ <th class="col-xs-1">Table Name</th>
+ <th class="col-xs-9">Columns</th>
+ <th class="col-xs-1"></th>
+ </tr>
+
+ <tr ng-repeat="dimension in model.dimensions" class="row">
+ <td class="col-xs-1">
+ <!-- ID -->
+ <b>{{($index + 1)}}</b>
</td>
- <!--Columns-->
- <td style="word-wrap:break-word;word-break:break-all;">
- <div ng-repeat="t in getDimType(dimension)">
- <div ng-switch="t">
- <dl class="dl-horizontal" ng-switch-when="hierarchy">
- <dt>Hierarchy</dt>
- <dd>{{dimension.column}}</dd>
- </dl>
- <dl class="dl-horizontal" ng-switch-when="derived">
- <dt>Derived</dt>
- <dd>{{dimension.derived}}</dd>
- </dl>
- <dl class="dl-horizontal" ng-switch-when="normal">
- <dt>Column</dt>
- <dd>{{dimension.columns}}</dd>
- </dl>
- </div>
- </div>
+ <td class="col-xs-1">
+ {{dimension.table}}
</td>
- <td ng-if="state.mode=='edit'">
- <!--edit button-->
+ <td class="col-xs-9">
+ <!-- Dimensions -->
+ <select ng-if="state.mode=='edit'" style="width: 100%"
+ ng-model="model.dimensions[$index].columns" required chosen multiple
+ ng-change=""
+ ng-options="column.name as column.name for column in getColumnsByTable(dimension.table)">
+ <option value=""></option>
+ </select>
+ </td>
+ <td class="col-xs-1">
<button class="btn btn-xs btn-info"
- ng-click="editDim(dimension)"><i class="fa fa-pencil"></i>
- </button>
- <!-- remove button-->
- <button class="btn btn-xs btn-danger"
- ng-click="removeDim(dimension)"><i class="fa fa-trash-o"></i>
+ ng-click="removeTableDimensions($index)"><i
+ class="fa fa-minus"></i>
</button>
</td>
</tr>
- </tbody>
- </table>
-</div>
-
-<div class="space-16"></div>
-<div class="callout callout-warning dimensions-conflict-area" ng-if="dimConflicts.length">
- <h4>There are following columns defined in multiple dimensions. <small>This is not recommended!</small></h4>
- <div class="row" ng-repeat="c in dimConflicts">
- <div class="col-xs-3">
- <code>{{c.table}}.{{c.column}}</code>
- </div>
- <div class="col-xs-3">
- <ul class="list-unstyled">
- <li ng-repeat="d in c.dims">{{d.id}} - {{d.name}}</li>
- </ul>
- </div>
- </div>
-</div>
-
-<!-- Edit Dimension Form -->
-<script type="text/ng-template" id="addEditDimension.html">
- <div class="modal-header">
- <h4 class="box-title lighter">{{dimState.editing ? 'Edit' : 'Add'}} Dimension
- <span class="label label-primary" ng-repeat="t in dimType">{{t}}</span>
- </h4>
- </div>
- <div class="modal-body">
- <ng-form name="edit_dim_form">
- <div class="row">
- <div class="col-xs-8">
- <!--Name-->
- <div class="form-group">
- <div class="row">
- <label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default"><b>Name</b></label>
- <div class="col-xs-12 col-sm-6">
- <input type="text" placeholder="Name.." class="form-control" name="dim_name"
- tooltip="dimension name.." tooltip-trigger="focus"
- ng-model="newDimension.name" required />
- </div>
- <div class="col-xs-12 col-sm-3">
- <div class="text-warning" ng-if="edit_dim_form.dim_name.$error.required && edit_dim_form.dim_name.$dirty">
- The Dimension Name is required.
- </div>
- </div>
- </div>
- </div>
-
- <!--Table Name: derived dimension only allows lookup tables-->
- <div class="form-group">
- <div class="row">
- <label class="control-label col-xs-12 col-sm-3 no-padding-right font-color-default"><b>Table Name</b></label>
- <div class="col-xs-12 col-sm-6" ng-if="dimType.indexOf('derived') >= 0">
- <select class="form-control" required="true" chosen data-placeholder="Select a lookup table"
- ng-model="newDimension.table" ng-options="table for table in availableTables.slice(1)">
- <option value=""></option>
- </select>
- </div>
- <div class="col-xs-12 col-sm-6" ng-if="dimType.indexOf('derived') == -1">
- <select class="form-control" required="true" chosen data-placeholder="Select a table"
- ng-model="newDimension.table" ng-options="table for table in availableTables">
- <option value=""></option>
- </select>
- </div>
- <div class="col-xs-12 col-sm-3">
- <div class="text-info" ng-if="dimType.indexOf('derived') >= 0">
- Derived dimension only comes from lookup table.
- </div>
- </div>
- </div>
- </div>
-
- <!--Normal Dimension: choose one column-->
- <div class="form-group" ng-if="dimType.indexOf('normal') >= 0">
- <div class="row">
- <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)">
- <option value=""></option>
- </select>
- </div>
- </div>
- </div>
+ </table>
- <!--Hierarchy Dimension-->
- <div class="form-group" ng-if="dimType.indexOf('hierarchy') >= 0">
- <div class="row">
- <div class="col-sm-6 col-sm-offset-3">
- <div ui-sortable="{containment: 'parent', placeholder: 'hierarchy-item-placeholder', forcePlaceholderSize: true, opacity: 0.8}"
- ng-model="newDimension.column" class="hierarchy-container">
- <div ng-repeat="hierarchyIndex in [] | range: newDimension.column.length" class="hierarchy-item">
- <div class="row">
- <div class="col-xs-2">
- <span class="badge">{{$index + 1}}</span>
- </div>
- <div class="col-xs-8">
- <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)" >
- <option value="">-- Select Column --</option>
- </select>
- </div>
- <div class="col-xs-2">
- <button type="button" class="pull-right btn btn-xs btn-danger" style="cursor: pointer " tooltip="Delete"
- ng-click="newDimension.column.splice($index, 1);">
- <i class="fa fa-trash-o"></i>
- </button>
- </div>
- </div>
- </div>
- </div>
- <div class="space-8"></div>
-
- <div class="row">
- <div class="col-xs-4">
- <button class="btn btn-xs btn-info"
- ng-click="newDimension.column.push('');">
- <i class="fa fa-plus"></i> New Hierarchy</button>
- </div>
- <div class="col-xs-8">
- <p class="help-block">Drag level into the order you prefer.</p>
- </div>
- </div>
- </div>
- </div>
- </div>
-
- <!--Derived Dimension-->
- <div ng-if="dimType.indexOf('derived') >= 0">
- <div class="form-group">
- <div class="row">
- <div class="col-sm-6 col-sm-offset-3">
- <div ng-repeat="derived in newDimension.derived track by $index">
- <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)" >
- <option value=""></option>
- </select>
- <button class="pull-right btn btn-xs btn-danger" style="cursor: pointer " tooltip="Delete"
- ng-click="newDimension.derived.splice($index, 1);">
- <i class="fa fa-trash-o"></i>
- </button>
- <div class="space-4"></div>
- </div>
- </div>
- <button class="btn btn-xs btn-info" ng-click="newDimension.derived.push('');">
- <i class="fa fa-plus"></i> New Derived</button>
- </div>
- </div>
- </div>
- </div>
- </div>
-
- <!--Tips-->
- <div class="col-xs-4">
- <div class="box box-solid">
- <div class="box-header">
- <h4 class="box-title">Tips</h4>
- </div>
- <div class="box-body">
- <div class="row">
- <div class="col-xs-12">
- <ol class="text-info">
- <li>Type in any input box for auto suggestion</li>
- <li>Pick up Fact Table from Star Schema Tables first</li>
- <li>Data Type should match with Hive Table's Data Type</li>
- <li>Join Type have to be same as will be used in query</li>
- <li>Using Hierarchy to inherit one dimension another</li>
- <li>Using Derived for One-One relationship between columns, like ID and Name</li>
- </ol>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </ng-form>
- </div>
- <div class="modal-footer">
- <button class="btn btn-primary" ng-disabled="edit_dim_form.$invalid" ng-click="ok()">OK</button>
- <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
- </div>
-</script>
-
-
-<script type="text/ng-template" id="autoGenDimension.html">
- <div class="modal-header">
- <h4 class="box-title lighter">Auto Generate Dimensions <small>This is a helper for you to batch generate dimensions.</small></h4>
- </div>
- <div class="modal-body">
- <div class="row">
- <div class="col-xs-8">
- <div class="box box-solid">
- <div class="box-header"><h4>Columns</h4></div>
- <div class="box-body">
- <ul class="list-unstyled columns-region">
- <li ng-repeat="table in availableTables track by $index">
- <h5 class="table-name-underline">
- <b>{{table}}</b>{{$index == 0 ? ' [Fact Table]' : ' [Lookup Table]'}}
- </h5>
- <ul class="list-unstyled">
- <li ng-repeat="col in availableColumns[table] track by col.table + '.' + col.name">
- <label>
- <input type="checkbox" ng-model="selectedColumns[table][col.name].selected"
- ng-disabled="selectedColumns[table][col.name].disabled">
- {{col.name}}
- </label>
- </li>
- </ul>
- </li>
- </ul>
- </div>
- </div>
- </div>
-
- <!--Tips-->
- <div class="col-xs-4">
- <div class="box box-solid">
- <div class="box-header">
- <h4 class="box-title">Auto Generate Rules</h4>
- </div>
- <div class="box-body">
- <div class="row">
- <div class="col-xs-12">
- <ol class="text-info">
- <li>Column is disabled once there is already a dimension referred this column.</li>
- <li>In fact table: one normal dimension will be auto generated per column.</li>
- <li>In lookup table: one derived dimension will be auto generated for all the selected columns.</li>
- </ol>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <div class="modal-footer">
- <button class="btn btn-primary" ng-disabled="" ng-click="ok()">OK</button>
- <button class="btn btn-warning" ng-click="cancel()">Cancel</button>
- </div>
-</script>
+</div>
</div>
http://git-wip-us.apache.org/repos/asf/incubator-kylin/blob/a2f4d320/webapp/app/partials/modelDesigner/model_info.html
----------------------------------------------------------------------
diff --git a/webapp/app/partials/modelDesigner/model_info.html b/webapp/app/partials/modelDesigner/model_info.html
index d91a0f0..9b9e786 100644
--- a/webapp/app/partials/modelDesigner/model_info.html
+++ b/webapp/app/partials/modelDesigner/model_info.html
@@ -29,7 +29,7 @@
</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="model.project" disabled/>
+ ng-model="state.project"/>
<span ng-if="state.mode=='view'">
{{model.project}}
</span>
@@ -37,11 +37,11 @@
</div>
</div>
- <!--Cube Name-->
+ <!--Model Name-->
<div class="form-group">
<div class="row">
<label class="col-xs-12 col-sm-3 control-label no-padding-right font-color-default">
- <b>Cube Name</b>
+ <b>Model Name</b>
</label>
<div class="col-xs-12 col-sm-6">
<input ng-if="state.mode=='edit'" name="model_name" type="text" class="form-control"