Merge branch 'master' of https://github.com/apache/zeppelin into py4jPythonInterpreter

This commit is contained in:
astroshim 2017-03-08 14:15:32 +09:00
commit c3f5b78d76
23 changed files with 945 additions and 638 deletions

3
.gitignore vendored
View file

@ -100,6 +100,9 @@ Thumbs.db
target/
**/target/
# maven flattened pom files
**/.flattened-pom.xml
# Generated by Jekyll
docs/_site/

View file

@ -25,7 +25,6 @@ cache:
- ${HOME}/R
- zeppelin-web/node
- zeppelin-web/node_modules
- zeppelin-web/bower_components
addons:
apt:

View file

@ -34,7 +34,7 @@ if [[ ($# -ne 1) || ( $1 == "--help") || $1 == "-h" ]]; then
usage
fi
TO_VERSION=$1
TO_VERSION="$1"
check_scala_version() {
for i in ${VALID_VERSIONS[*]}; do [ $i = "$1" ] && return 0; done
@ -42,12 +42,14 @@ check_scala_version() {
exit 1
}
check_scala_version "$TO_VERSION"
check_scala_version "${TO_VERSION}"
if [ $TO_VERSION = "2.11" ]; then
if [ "${TO_VERSION}" = "2.11" ]; then
FROM_VERSION="2.10"
SCALA_LIB_VERSION="2.11.7"
else
FROM_VERSION="2.11"
SCALA_LIB_VERSION="2.10.5"
fi
sed_i() {
@ -57,11 +59,17 @@ sed_i() {
export -f sed_i
BASEDIR=$(dirname $0)/..
find "$BASEDIR" -name 'pom.xml' -not -path '*target*' -print \
-exec bash -c "sed_i 's/\(artifactId.*\)_'$FROM_VERSION'/\1_'$TO_VERSION'/g' {}" \;
find "${BASEDIR}" -name 'pom.xml' -not -path '*target*' -print \
-exec bash -c "sed_i 's/\(artifactId.*\)_'${FROM_VERSION}'/\1_'${TO_VERSION}'/g' {}" \;
# Also update <scala.binary.version> in parent POM
# update <scala.binary.version> in parent POM
# Match any scala binary version to ensure idempotency
sed_i '1,/<scala\.binary\.version>[0-9]*\.[0-9]*</s/<scala\.binary\.version>[0-9]*\.[0-9]*</<scala.binary.version>'$TO_VERSION'</' \
"$BASEDIR/pom.xml"
sed_i '1,/<scala\.binary\.version>[0-9]*\.[0-9]*</s/<scala\.binary\.version>[0-9]*\.[0-9]*</<scala.binary.version>'${TO_VERSION}'</' \
"${BASEDIR}/pom.xml"
# update <scala.version> in parent POM
# This is to make variables in leaf pom to be substituted to real value when flattened-pom is created.
# maven-flatten plugin doesn't take properties defined under profile even if scala-2.11/scala-2.10 is activated via -Pscala-2.11/-Pscala-2.10,
# and use default defined properties to create flatten pom.
sed_i '1,/<scala\.version>[0-9]*\.[0-9]*\.[0-9]*</s/<scala\.version>[0-9]*\.[0-9]*\.[0-9]*</<scala.version>'${SCALA_LIB_VERSION}'</' \
"${BASEDIR}/pom.xml"

View file

@ -167,6 +167,10 @@ There are more JDBC interpreter properties you can specify like below.
<td>default.jceks.credentialKey</td>
<td>jceks credential key</td>
</tr>
<tr>
<td>zeppelin.jdbc.precode</td>
<td>Some SQL which executes while opening connection</td>
</tr>
</table>
You can also add more properties by using this [method](http://docs.oracle.com/javase/7/docs/api/java/sql/DriverManager.html#getConnection%28java.lang.String,%20java.util.Properties%29).
@ -423,8 +427,13 @@ Here are some examples you can refer to. Including the below connectors, you can
<td>default.password</td>
<td>hive_password</td>
</tr>
<tr>
<td>hive.proxy.user</td>
<td>true or false</td>
</table>
Connection to Hive JDBC with a proxy user can be disabled with `hive.proxy.user` property (set to true by default)
[Apache Hive 1 JDBC Driver Docs](https://cwiki.apache.org/confluence/display/Hive/HiveServer2+Clients#HiveServer2Clients-JDBC)
[Apache Hive 2 JDBC Driver Docs](https://cwiki.apache.org/confluence/display/Hive/HiveServer2+Clients#HiveServer2Clients-JDBC)

View file

@ -111,9 +111,9 @@ You can also install 3rd party interpreters located in the maven repository by u
./bin/install-interpreter.sh --name interpreter1 --artifact groupId1:artifact1:version1
```
The above command will download maven artifact `groupId1:artifact1:version1` and all of it's transitive dependencies into `interpreter/interpreter1` directory.
The above command will download maven artifact `groupId1:artifact1:version1` and all of its transitive dependencies into `interpreter/interpreter1` directory.
After restart Zeppelin, then [create interpreter setting](../manual/interpreters.html#what-is-zeppelin-interpreter) and [bind it with your notebook](../manual/interpreters.html#what-is-zeppelin-interpreter-setting).
After restart Zeppelin, then [create interpreter setting](../manual/interpreters.html#what-is-zeppelin-interpreter) and [bind it with your note](../manual/interpreters.html#what-is-zeppelin-interpreter-setting).
#### Install multiple 3rd party interpreters at once

View file

@ -14,14 +14,7 @@
*/
package org.apache.zeppelin.jdbc;
import static org.apache.commons.lang.StringUtils.containsIgnoreCase;
import static org.apache.commons.lang.StringUtils.isEmpty;
import static org.apache.commons.lang.StringUtils.isNotEmpty;
import static org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod.KERBEROS;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.PrivilegedExceptionAction;
import java.sql.Connection;
import java.sql.DriverManager;
@ -37,11 +30,11 @@ import java.util.Map;
import java.util.Properties;
import java.util.Set;
import com.google.common.base.Throwables;
import org.apache.commons.dbcp2.ConnectionFactory;
import org.apache.commons.dbcp2.DriverManagerConnectionFactory;
import org.apache.commons.dbcp2.PoolableConnectionFactory;
import org.apache.commons.dbcp2.PoolingDriver;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.pool2.ObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.hadoop.conf.Configuration;
@ -49,7 +42,10 @@ import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.alias.CredentialProvider;
import org.apache.hadoop.security.alias.CredentialProviderFactory;
import org.apache.thrift.transport.TTransportException;
import org.apache.zeppelin.interpreter.*;
import org.apache.zeppelin.interpreter.Interpreter;
import org.apache.zeppelin.interpreter.InterpreterContext;
import org.apache.zeppelin.interpreter.InterpreterException;
import org.apache.zeppelin.interpreter.InterpreterResult;
import org.apache.zeppelin.interpreter.InterpreterResult.Code;
import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
import org.apache.zeppelin.jdbc.security.JDBCSecurityImpl;
@ -61,9 +57,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;
import static org.apache.commons.lang.StringUtils.containsIgnoreCase;
import static org.apache.commons.lang.StringUtils.isEmpty;
import static org.apache.commons.lang.StringUtils.isNotEmpty;
import static org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod.KERBEROS;
/**
* JDBC interpreter for Zeppelin. This interpreter can also be used for accessing HAWQ,
@ -103,6 +103,7 @@ public class JDBCInterpreter extends Interpreter {
static final String PASSWORD_KEY = "password";
static final String JDBC_JCEKS_FILE = "jceks.file";
static final String JDBC_JCEKS_CREDENTIAL_KEY = "jceks.credentialKey";
static final String ZEPPELIN_JDBC_PRECODE_KEY = "zeppelin.jdbc.precode";
static final String DOT = ".";
private static final char WHITESPACE = ' ';
@ -340,6 +341,9 @@ public class JDBCInterpreter extends Interpreter {
if (!getJDBCConfiguration(user).isConnectionInDBDriverPool(propertyKey)) {
createConnectionPool(url, user, propertyKey, properties);
try (Connection connection = DriverManager.getConnection(jdbcDriver)) {
executePrecode(connection);
}
}
return DriverManager.getConnection(jdbcDriver);
}
@ -374,16 +378,20 @@ public class JDBCInterpreter extends Interpreter {
if (lastIndexOfUrl == -1) {
lastIndexOfUrl = connectionUrl.length();
}
connectionUrl.insert(lastIndexOfUrl, ";hive.server2.proxy.user=" + user + ";");
boolean hasProxyUser = property.containsKey("hive.proxy.user");
if (!hasProxyUser || !property.getProperty("hive.proxy.user").equals("false")){
logger.debug("Using hive proxy user");
connectionUrl.insert(lastIndexOfUrl, ";hive.server2.proxy.user=" + user + ";");
}
connection = getConnectionFromPool(connectionUrl.toString(),
user, propertyKey, properties);
user, propertyKey, properties);
} else {
UserGroupInformation ugi = null;
try {
ugi = UserGroupInformation.createProxyUser(user,
UserGroupInformation.getCurrentUser());
ugi = UserGroupInformation.createProxyUser(
user, UserGroupInformation.getCurrentUser());
} catch (Exception e) {
logger.error("Error in createProxyUser", e);
logger.error("Error in getCurrentUser", e);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(e.getMessage()).append("\n");
stringBuilder.append(e.getCause());
@ -540,6 +548,20 @@ public class JDBCInterpreter extends Interpreter {
return queries;
}
private void executePrecode(Connection connection) throws SQLException {
String precode = getProperty(ZEPPELIN_JDBC_PRECODE_KEY);
if (StringUtils.isNotBlank(precode)) {
precode = StringUtils.trim(precode);
logger.info("Run SQL precode '{}'", precode);
try (Statement statement = connection.createStatement()) {
statement.execute(precode);
if (!connection.getAutoCommit()) {
connection.commit();
}
}
}
}
private InterpreterResult executeSql(String propertyKey, String sql,
InterpreterContext interpreterContext) {
Connection connection;
@ -761,4 +783,3 @@ public class JDBCInterpreter extends Interpreter {
}
}
}

View file

@ -63,6 +63,12 @@
"propertyName": "zeppelin.jdbc.principal",
"defaultValue": "",
"description": "Kerberos principal"
},
"zeppelin.jdbc.precode": {
"envName": null,
"propertyName": "zeppelin.jdbc.precode",
"defaultValue": "",
"description": "SQL which executes while opening connection"
}
},
"editor": {

View file

@ -43,6 +43,9 @@ import org.junit.Before;
import org.junit.Test;
import com.mockrunner.jdbc.BasicJDBCTestCaseAdapter;
import static org.apache.zeppelin.jdbc.JDBCInterpreter.ZEPPELIN_JDBC_PRECODE_KEY;
/**
* JDBC interpreter unit tests
*/
@ -386,4 +389,43 @@ public class JDBCInterpreterTest extends BasicJDBCTestCaseAdapter {
assertNull(user2JDBC2Conf.getPropertyMap("default").get("password"));
jdbc2.close();
}
@Test
public void testPrecode() throws SQLException, IOException {
Properties properties = new Properties();
properties.setProperty("default.driver", "org.h2.Driver");
properties.setProperty("default.url", getJdbcConnection());
properties.setProperty("default.user", "");
properties.setProperty("default.password", "");
properties.setProperty(ZEPPELIN_JDBC_PRECODE_KEY, "SET @testVariable=1");
JDBCInterpreter jdbcInterpreter = new JDBCInterpreter(properties);
jdbcInterpreter.open();
String sqlQuery = "select @testVariable";
InterpreterResult interpreterResult = jdbcInterpreter.interpret(sqlQuery, interpreterContext);
assertEquals(InterpreterResult.Code.SUCCESS, interpreterResult.code());
assertEquals(InterpreterResult.Type.TABLE, interpreterResult.message().get(0).getType());
assertEquals("@TESTVARIABLE\n1\n", interpreterResult.message().get(0).getData());
}
@Test
public void testIncorrectPrecode() throws SQLException, IOException {
Properties properties = new Properties();
properties.setProperty("default.driver", "org.h2.Driver");
properties.setProperty("default.url", getJdbcConnection());
properties.setProperty("default.user", "");
properties.setProperty("default.password", "");
properties.setProperty(ZEPPELIN_JDBC_PRECODE_KEY, "incorrect command");
JDBCInterpreter jdbcInterpreter = new JDBCInterpreter(properties);
jdbcInterpreter.open();
String sqlQuery = "select 1";
InterpreterResult interpreterResult = jdbcInterpreter.interpret(sqlQuery, interpreterContext);
assertEquals(InterpreterResult.Code.ERROR, interpreterResult.code());
assertEquals(InterpreterResult.Type.TEXT, interpreterResult.message().get(0).getType());
}
}

File diff suppressed because it is too large Load diff

28
pom.xml
View file

@ -308,6 +308,32 @@
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<flattenMode>ossrh</flattenMode>
<updatePomFile>true</updatePomFile>
</configuration>
<executions>
<execution>
<id>flatten</id>
<phase>process-resources</phase>
<goals>
<goal>flatten</goal>
</goals>
</execution>
<execution>
<id>flatten.clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Test coverage plugin -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
@ -475,7 +501,7 @@
<version>${plugin.deploy.version}</version>
</plugin>
<!--TODO(alex): make part of the build and reconcile conflicts
<!--TODO(alex): make part of the build and reconcile conflicts
<plugin>
<groupId>com.ning.maven.plugins</groupId>
<artifactId>maven-duplicate-finder-plugin</artifactId>

View file

@ -54,8 +54,11 @@ def getBuildStatus(author, commit):
# get latest 25 builds
resp = requests.get(url=travisApi + "/repos/" + author + "/zeppelin/builds")
data = json.loads(resp.text)
build = None
if len(data) == 0:
return build;
for b in data:
if b["commit"][:len(commit)] == commit:
resp = requests.get(url=travisApi + "/repos/" + author + "/zeppelin/builds/" + str(b["id"]))
@ -103,8 +106,8 @@ for sleep in check:
info("Get build status ...")
build = getBuildStatus(author, commit)
if build == None:
info("Can't find build for commit= " + commit)
sys.exit(1)
info("Can't find build for commit " + commit + " from " + author)
sys.exit(2)
print("Build https://travis-ci.org/" + author + "/zeppelin/builds/" + str(build["id"]))
failure, running = printBuildStatus(build)

View file

@ -34,6 +34,10 @@ public class HeliumPackage {
// [[ .. and .. and .. ] or [ .. and .. and ..] ..]
private String license;
private String icon;
private String published;
private String groupId; // get groupId of INTERPRETER type package
private String artifactId; // get artifactId of INTERPRETER type package
private SpellPackageInfo spell;
private Map<String, Object> config;
@ -108,6 +112,18 @@ public class HeliumPackage {
return icon;
}
public String getPublishedDate() {
return published;
}
public String getGroupId() {
return groupId;
}
public String getArtifactId() {
return artifactId;
}
public SpellPackageInfo getSpellInfo() {
return spell;
}

View file

@ -23,7 +23,15 @@ export default function HeliumCtrl($scope, $rootScope, $sce,
$scope.showVersions = {};
$scope.bundleOrder = [];
$scope.bundleOrderChanged = false;
$scope.vizTypePkg = {}
$scope.spellTypePkg = {}
$scope.intpTypePkg = {}
$scope.appTypePkg = {}
$scope.numberOfEachPackageByType = {}
$scope.allPackageTypes = [HeliumType][0]
$scope.pkgListByType = 'VISUALIZATION'
$scope.defaultPackageConfigs = {}; // { pkgName, [{name, type, desc, value, defaultValue}] }
$scope.intpDefaultIcon = $sce.trustAsHtml('<img src="../assets/images/maven_default_icon.png" style="width: 12px"/>');
function init() {
// get all package info and set config
@ -31,6 +39,7 @@ export default function HeliumCtrl($scope, $rootScope, $sce,
.then(({ pkgSearchResults, defaultPackages }) => {
$scope.pkgSearchResults = pkgSearchResults;
$scope.defaultPackages = defaultPackages;
classifyPkgType($scope.defaultPackages)
return heliumService.getAllPackageConfigs()
})
.then(defaultPackageConfigs => {
@ -45,6 +54,38 @@ export default function HeliumCtrl($scope, $rootScope, $sce,
});
}
var classifyPkgType = function(packageInfos) {
var vizTypePkg = {}
var spellTypePkg = {}
var intpTypePkg = {}
var appTypePkg = {}
for (var name in packageInfos) {
var pkgs = packageInfos[name]
var pkgType = pkgs.pkg.type
switch (pkgType) {
case HeliumType.VISUALIZATION:
vizTypePkg[name] = pkgs;
break;
case HeliumType.SPELL:
spellTypePkg[name] = pkgs;
break;
case HeliumType.INTERPRETER:
intpTypePkg[name] = pkgs;
break;
case HeliumType.APPLICATION:
appTypePkg[name] = pkgs;
break;
}
}
$scope.vizTypePkg = vizTypePkg
$scope.spellTypePkg = spellTypePkg
$scope.appTypePkg = appTypePkg
$scope.intpTypePkg = intpTypePkg
};
$scope.bundleOrderListeners = {
accept: function(sourceItemHandleScope, destSortableScope) {return true;},
itemMoved: function(event) {},
@ -108,40 +149,58 @@ export default function HeliumCtrl($scope, $rootScope, $sce,
return license;
}
$scope.enable = function(name, artifact) {
$scope.enable = function(name, artifact, type, groupId) {
var license = getLicense(name, artifact);
var confirm = BootstrapDialog.confirm({
closable: false,
closeByBackdrop: false,
closeByKeyboard: false,
var mavenArtifactInfoToHTML = groupId +':'+ artifact.split('@')[0] + ':' + artifact.split('@')[1];
var zeppelinVersion = $rootScope.zeppelinVersion;
var url = 'https://zeppelin.apache.org/docs/' + zeppelinVersion + '/manual/interpreterinstallation.html';
var confirm = ''
if (type === 'INTERPRETER') {
confirm = BootstrapDialog.show({
title: '',
message: 'Do you want to enable ' + name + '?' +
'<div style="color:gray">' + artifact + '</div>' +
'<div style="border-top: 1px solid #efefef; margin-top: 10px; padding-top: 5px;">License</div>' +
'<div style="color:gray">' + license + '</div>',
callback: function(result) {
if (result) {
confirm.$modalFooter.find('button').addClass('disabled');
confirm.$modalFooter.find('button:contains("OK")')
.html('<i class="fa fa-circle-o-notch fa-spin"></i> Enabling');
heliumService.enable(name, artifact).
success(function(data, status) {
init();
confirm.close();
}).
error(function(data, status) {
confirm.close();
console.log('Failed to enable package %o %o. %o', name, artifact, data);
BootstrapDialog.show({
title: 'Error on enabling ' + name,
message: data.message
});
});
return false;
}
}
message: '<p>Below command will download maven artifact ' +
'<code style="font-size: 11.5px; background-color: #f5f5f5; color: #0a0a0a">' +
mavenArtifactInfoToHTML + '</code>' +
' and all of its transitive dependencies into interpreter/interpreter-name directory.<p>' +
'<div class="highlight"><pre><code class="text language-text" data-lang="text" style="font-size: 11.5px">' +
'./bin/install-interpreter.sh --name "interpreter-name" --artifact ' +
mavenArtifactInfoToHTML +' </code></pre>' +
'<p>After restart Zeppelin, create interpreter setting and bind it with your note. ' +
'For more detailed information, see <a target="_blank" href=' +
url + '>Interpreter Installation.</a></p>'
});
} else {
confirm = BootstrapDialog.confirm({
closable: false,
closeByBackdrop: false,
closeByKeyboard: false,
title: '',
message: 'Do you want to enable ' + name + '?' +
'<div style="color:gray">' + artifact + '</div>' +
'<div style="border-top: 1px solid #efefef; margin-top: 10px; padding-top: 5px;">License</div>' +
'<div style="color:gray">' + license + '</div>',
callback: function (result) {
if (result) {
confirm.$modalFooter.find('button').addClass('disabled');
confirm.$modalFooter.find('button:contains("OK")')
.html('<i class="fa fa-circle-o-notch fa-spin"></i> Enabling');
heliumService.enable(name, artifact, type).success(function (data, status) {
init();
confirm.close();
}).error(function (data, status) {
confirm.close();
console.log('Failed to enable package %o %o. %o', name, artifact, data);
BootstrapDialog.show({
title: 'Error on enabling ' + name,
message: data.message
});
});
return false;
}
}
});
}
};
$scope.disable = function(name) {
@ -194,6 +253,20 @@ export default function HeliumCtrl($scope, $rootScope, $sce,
!$scope.isLocalPackage(pkgSearchResult);
};
$scope.hasMavenLink = function(pkgSearchResult) {
const pkg = pkgSearchResult.pkg;
return (pkg.type === HeliumType.APPLICATION || pkg.type === HeliumType.INTERPRETER) &&
!$scope.isLocalPackage(pkgSearchResult);
};
$scope.getPackageSize = function(pkgSearchResult, targetPkgType) {
var result = []
_.map(pkgSearchResult, function (pkg) {
result.push(_.find(pkg, {type: targetPkgType}))
})
return _.compact(result).length
}
$scope.configExists = function(pkgSearchResult) {
// helium package config is persisted per version
return pkgSearchResult.pkg.config && pkgSearchResult.pkg.artifact;

View file

@ -136,6 +136,33 @@
color: #636363;
}
.heliumLearnMore {
margin-top:10px;
}
.heliumLearnMore a {
cursor:pointer;
margin-right:10px;
text-decoration:none;
}
.heliumRepoBtn {
margin-right: 8px;
}
.heliumRepoBtn:hover, .heliumRepoBtn:focus {
margin-right: 8px;
outline: 0;
}
.localPkgInfo {
margin: 10px 12px 0 0;
font-size: 11px;
font-style: italic;
color: #aaaaaa;
text-align: right;
}
.heliumConfig {
margin-top: 30px;
margin-bottom: 10px;
@ -147,10 +174,6 @@
margin-bottom: 15px;
}
.heliumConfigValueInput {
}
.heliumConfigValueText {
vertical-align: top;
}

View file

@ -18,6 +18,23 @@ limitations under the License.
<h3 class="new_h3">
Helium
</h3>
<div class="pull-right heliumLearnMore">
<a target="_blank"
class="helium-repo-btn"
ng-href="https://zeppelin.apache.org/helium_packages.html"
tooltip-placement="bottom"
tooltip="Learn more">
<i class="icon-question" ng-style="{color: 'black'}"></i>
</a>
<button tabindex="0" class="btn btn-default btn-sm heliumRepoBtn helium-popover"
role="button"
ng-repeat="pkgTypes in allPackageTypes"
ng-click="$parent.pkgListByType = pkgTypes">
<i class="fa fa-cube"></i>
{{pkgTypes}}
</button>
<p class="localPkgInfo">* Local registry package's name is gray colored.</p>
</div>
</div>
</div>
<div ng-show="bundleOrder.length > 1"
@ -34,8 +51,8 @@ limitations under the License.
</div>
</div>
<span class="saveLink"
ng-show="bundleOrderChanged"
ng-click="saveBundleOrder()">
ng-show="bundleOrderChanged"
ng-click="saveBundleOrder()">
save
</span>
</div>
@ -44,28 +61,46 @@ limitations under the License.
</div>
<div class="box width-full heliumPackageContainer">
<div class="row"
style="padding-bottom: 15px"
ng-if="getPackageSize(defaultPackages, pkgListByType) === 0">
<div class="col-md-12 gray40-message">
<em>Currently there is no available package to be listed</em>
</div>
</div>
<div class="row heliumPackageList"
ng-repeat="(pkgName, pkgSearchResult) in defaultPackages">
ng-repeat="pkgSearchResult in defaultPackages | toArray:false | orderBy: 'pkg.published':true"
ng-show="$parent.pkgListByType === pkgSearchResult.pkg.type">
<div class="col-md-12">
<div class="heliumPackageHead">
<div class="heliumPackageIcon"
ng-if="pkgSearchResult.pkg.type !== 'INTERPRETER'"
ng-bind-html=pkgSearchResult.pkg.icon></div>
<div class="heliumPackageIcon"
ng-if="pkgSearchResult.pkg.type === 'INTERPRETER'"
ng-bind-html=intpDefaultIcon></div>
<div class="heliumPackageName">
<span ng-if="hasNpmLink(pkgSearchResult)">
<a target="_blank" href="https://www.npmjs.com/package/{{pkgName}}">{{pkgName}}</a>
<a target="_blank" href="https://www.npmjs.com/package/{{pkgSearchResult.pkg.name}}">{{pkgSearchResult.pkg.name}}</a>
</span>
<span ng-if="!hasNpmLink(pkgSearchResult)" ng-class="{'heliumLocalPackage': isLocalPackage(pkgSearchResult)}">
{{pkgName}}
<span ng-if="!hasNpmLink(pkgSearchResult) && !hasMavenLink(pkgSearchResult)" ng-class="{'heliumLocalPackage': isLocalPackage(pkgSearchResult)}">
{{pkgSearchResult.pkg.name}}
</span>
<span ng-if="hasMavenLink(pkgSearchResult)">
<a target="_blank"
href="http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22{{pkgSearchResult.pkg.artifact.split('@')[0]}}%22%20AND%20v%3A%22{{pkgSearchResult.pkg.artifact.split('@')[1]}}%22">
{{pkgSearchResult.pkg.name}}
</a>
</span>
<span class="heliumType">{{pkgSearchResult.pkg.type}}</span>
</div>
<div ng-show="!pkgSearchResult.enabled"
ng-click="enable(pkgName, pkgSearchResult.pkg.artifact)"
ng-click="enable(pkgSearchResult.pkg.name, pkgSearchResult.pkg.artifact, pkgSearchResult.pkg.type, pkgSearchResult.pkg.groupId)"
class="btn btn-success btn-xs"
style="float:right">Enable</div>
<div ng-show="pkgSearchResult.enabled"
ng-click="disable(pkgName)"
ng-click="disable(pkgSearchResult.pkg.name)"
ng-if="pkgSearchResult.pkg.type !== 'INTERPRETER'"
class="btn btn-info btn-xs"
style="float:right">Disable</div>
<div ng-show="configExists(pkgSearchResult)"
@ -76,20 +111,27 @@ limitations under the License.
</div>
<div ng-class="{heliumPackageDisabledArtifact: !pkgSearchResult.enabled, heliumPackageEnabledArtifact: pkgSearchResult.enabled}">
{{pkgSearchResult.pkg.artifact}}
<span ng-show="pkgSearchResults[pkgName].length > 0"
ng-click="toggleVersions(pkgName)">
<span ng-show="pkgSearchResults[pkgSearchResult.pkg.name].length > 0"
ng-click="toggleVersions(pkgSearchResult.pkg.name)">
versions
</span>
</div>
<ul class="heliumPackageVersions"
ng-show="showVersions[pkgName]">
ng-show="showVersions[pkgSearchResult.pkg.name]">
<li class="heliumPackageDisabledArtifact"
ng-repeat="pkgSearchResult in pkgSearchResults[pkgName]">
ng-repeat="pkgSearchResult in pkgSearchResults[pkgSearchResult.pkg.name]">
{{pkgSearchResult.pkg.artifact}} -
<span ng-click="enable(pkgName, pkgSearchResult.pkg.artifact)"
<span ng-click="enable(pkgSearchResult.pkg.name, pkgSearchResult.pkg.artifact, pkgSearchResult.pkg.type, pkgSearchResult.pkg.groupId)"
ng-if="pkgSearchResult.pkg.type !== 'INTERPRETER'"
style="margin-left:3px;cursor:pointer;text-decoration: underline;color:#3071a9">
enable
</span>
<a target="_blank"
ng-if="pkgSearchResult.pkg.type === 'INTERPRETER'"
style="margin-left:3px;cursor:pointer;text-decoration: underline;color:#3071a9"
href="http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22{{pkgSearchResult.pkg.artifact.split('@')[0]}}%22%20AND%20v%3A%22{{pkgSearchResult.pkg.artifact.split('@')[1]}}%22">
see more
</a>
</li>
</ul>
<div class="heliumPackageDescription">

View file

@ -267,9 +267,7 @@ function ResultCtrl($scope, $rootScope, $route, $window, $routeParams, $location
$scope.renderDefaultDisplay = function(targetElemId, type, data, refresh) {
if (type === DefaultDisplayType.TABLE) {
$timeout(function() {
$scope.renderGraph(targetElemId, $scope.graphMode, refresh);
}, 10);
$scope.renderGraph(targetElemId, $scope.graphMode, refresh);
} else if (type === DefaultDisplayType.HTML) {
renderHtml(targetElemId, data);
} else if (type === DefaultDisplayType.ANGULAR) {

View file

@ -28,10 +28,10 @@ limitations under the License.
&& config.graph.optionOpen && !asIframe && !viewOnly">
<div ng-repeat="viz in builtInTableDataVisualizationList track by $index"
id="trsetting{{id}}_{{viz.id}}"
ng-show="graphMode == viz.id"></div>
ng-if="graphMode == viz.id"></div>
<div ng-repeat="viz in builtInTableDataVisualizationList track by $index"
id="vizsetting{{id}}_{{viz.id}}"
ng-show="graphMode == viz.id"></div>
ng-if="graphMode == viz.id"></div>
</div>
<!-- graph -->
@ -40,7 +40,7 @@ limitations under the License.
ng-class="{'noOverflow': graphMode=='table'}">
<div ng-repeat="viz in builtInTableDataVisualizationList track by $index"
id="p{{id}}_{{viz.id}}"
ng-show="graphMode == viz.id">
ng-if="graphMode == viz.id">
</div>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View file

@ -15,4 +15,6 @@
export const HeliumType = {
VISUALIZATION: 'VISUALIZATION',
SPELL: 'SPELL',
INTERPRETER: 'INTERPRETER',
APPLICATION: 'APPLICATION',
}

View file

@ -89,7 +89,11 @@ function websocketEvents($rootScope, $websocket, $location, baseUrlSrv) {
label: 'Cancel',
action: function(dialog) {
dialog.close();
$location.path('/');
// using $rootScope.apply to trigger angular digest cycle
// changing $location.path inside bootstrap modal wont trigger digest
$rootScope.$apply(function() {
$location.path('/');
});
}
}];
}

View file

@ -34,7 +34,7 @@ import java.net.URL;
import java.util.*;
/**
* Load helium visualization
* Load helium visualization & spell
*/
public class HeliumBundleFactory {
Logger logger = LoggerFactory.getLogger(HeliumBundleFactory.class);

View file

@ -12,6 +12,10 @@
"babel-core": "^6.23.1",
"babel-loader": "^6.3.2",
"babel-preset-es2015": "^6.22.0",
"babel-preset-stage-0": "^6.22.0"
"babel-preset-stage-0": "^6.22.0",
"css-loader": "^0.26.2",
"style-loader": "^0.13.2",
"url-loader": "^0.5.8",
"file-loader": "^0.10.1"
}
}

View file

@ -19,11 +19,36 @@ module.exports = {
entry: './load.js',
output: { path: './', filename: 'helium.bundle.js', },
module: {
loaders: [{
loaders: [
{
test: /\.js$/,
// DON'T exclude. since zeppelin will bundle all necessary packages: `exclude: /node_modules/,`
loader: 'babel-loader',
query: { presets: ['es2015', 'stage-0'] },
}]
},
{
test: /(\.css)$/,
loaders: ['style', 'css?sourceMap&importLoaders=1'],
},
{
test: /\.woff(\?\S*)?$/,
loader: 'url-loader?limit=10000&minetype=application/font-woff',
},
{
test: /\.woff2(\?\S*)?$/,
loader: 'url-loader?limit=10000&minetype=application/font-woff',
},
{
test: /\.eot(\?\S*)?$/,
loader: 'url-loader',
}, {
test: /\.ttf(\?\S*)?$/,
loader: 'url-loader',
},
{
test: /\.svg(\?\S*)?$/,
loader: 'url-loader',
},
],
}
}