Merge remote-tracking branch 'upstream/master' into ZEPPELIN-2403

This commit is contained in:
Tinkoff DWH 2017-04-27 15:40:36 +05:00
commit 07160e00eb
25 changed files with 216 additions and 73 deletions

View file

@ -64,7 +64,7 @@ fi
. "${bin}/common.sh"
ZEPPELIN_INTP_CLASSPATH=""
ZEPPELIN_INTP_CLASSPATH="${CLASSPATH}"
# construct classpath
if [[ -d "${ZEPPELIN_HOME}/zeppelin-interpreter/target/classes" ]]; then
@ -190,8 +190,6 @@ fi
addJarInDirForIntp "${LOCAL_INTERPRETER_REPO}"
CLASSPATH+=":${ZEPPELIN_INTP_CLASSPATH}"
if [[ ! -z "$ZEPPELIN_IMPERSONATE_USER" ]]; then
suid="$(id -u ${ZEPPELIN_IMPERSONATE_USER})"
if [[ -n "${suid}" || -z "${SPARK_SUBMIT}" ]]; then
@ -204,12 +202,12 @@ fi
if [[ -n "${SPARK_SUBMIT}" ]]; then
if [[ -n "$ZEPPELIN_IMPERSONATE_USER" ]] && [[ "$ZEPPELIN_IMPERSONATE_SPARK_PROXY_USER" != "false" ]]; then
INTERPRETER_RUN_COMMAND+=' '` echo ${SPARK_SUBMIT} --class ${ZEPPELIN_SERVER} --driver-class-path \"${ZEPPELIN_INTP_CLASSPATH_OVERRIDES}:${CLASSPATH}\" --driver-java-options \"${JAVA_INTP_OPTS}\" ${SPARK_SUBMIT_OPTIONS} --proxy-user ${ZEPPELIN_IMPERSONATE_USER} ${SPARK_APP_JAR} ${PORT}`
INTERPRETER_RUN_COMMAND+=' '` echo ${SPARK_SUBMIT} --class ${ZEPPELIN_SERVER} --driver-class-path \"${ZEPPELIN_INTP_CLASSPATH_OVERRIDES}:${ZEPPELIN_INTP_CLASSPATH}\" --driver-java-options \"${JAVA_INTP_OPTS}\" ${SPARK_SUBMIT_OPTIONS} --proxy-user ${ZEPPELIN_IMPERSONATE_USER} ${SPARK_APP_JAR} ${PORT}`
else
INTERPRETER_RUN_COMMAND+=' '` echo ${SPARK_SUBMIT} --class ${ZEPPELIN_SERVER} --driver-class-path \"${ZEPPELIN_INTP_CLASSPATH_OVERRIDES}:${CLASSPATH}\" --driver-java-options \"${JAVA_INTP_OPTS}\" ${SPARK_SUBMIT_OPTIONS} ${SPARK_APP_JAR} ${PORT}`
INTERPRETER_RUN_COMMAND+=' '` echo ${SPARK_SUBMIT} --class ${ZEPPELIN_SERVER} --driver-class-path \"${ZEPPELIN_INTP_CLASSPATH_OVERRIDES}:${ZEPPELIN_INTP_CLASSPATH}\" --driver-java-options \"${JAVA_INTP_OPTS}\" ${SPARK_SUBMIT_OPTIONS} ${SPARK_APP_JAR} ${PORT}`
fi
else
INTERPRETER_RUN_COMMAND+=' '` echo ${ZEPPELIN_RUNNER} ${JAVA_INTP_OPTS} ${ZEPPELIN_INTP_MEM} -cp ${ZEPPELIN_INTP_CLASSPATH_OVERRIDES}:${CLASSPATH} ${ZEPPELIN_SERVER} ${PORT} `
INTERPRETER_RUN_COMMAND+=' '` echo ${ZEPPELIN_RUNNER} ${JAVA_INTP_OPTS} ${ZEPPELIN_INTP_MEM} -cp ${ZEPPELIN_INTP_CLASSPATH_OVERRIDES}:${ZEPPELIN_INTP_CLASSPATH} ${ZEPPELIN_SERVER} ${PORT} `
fi
if [[ ! -z "$ZEPPELIN_IMPERSONATE_USER" ]] && [[ -n "${suid}" || -z "${SPARK_SUBMIT}" ]]; then

View file

@ -71,7 +71,7 @@ addJarInDir "${ZEPPELIN_HOME}/zeppelin-zengine/target/lib"
addJarInDir "${ZEPPELIN_HOME}/zeppelin-server/target/lib"
addJarInDir "${ZEPPELIN_HOME}/zeppelin-web/target/lib"
CLASSPATH+=":${ZEPPELIN_CLASSPATH}"
ZEPPELIN_CLASSPATH="$CLASSPATH:$ZEPPELIN_CLASSPATH"
if [[ ! -d "${ZEPPELIN_LOG_DIR}" ]]; then
echo "Log dir doesn't exist, create ${ZEPPELIN_LOG_DIR}"
@ -83,4 +83,4 @@ if [[ ! -d "${ZEPPELIN_PID_DIR}" ]]; then
$(mkdir -p "${ZEPPELIN_PID_DIR}")
fi
exec $ZEPPELIN_RUNNER $JAVA_OPTS -cp $ZEPPELIN_CLASSPATH_OVERRIDES:$CLASSPATH $ZEPPELIN_SERVER "$@"
exec $ZEPPELIN_RUNNER $JAVA_OPTS -cp $ZEPPELIN_CLASSPATH_OVERRIDES:${ZEPPELIN_CLASSPATH} $ZEPPELIN_SERVER "$@"

View file

@ -149,7 +149,7 @@ public class JDBCInterpreter extends Interpreter {
logger.debug("propertyKey: {}", propertyKey);
String[] keyValue = propertyKey.split("\\.", 2);
if (2 == keyValue.length) {
logger.info("key: {}, value: {}", keyValue[0], keyValue[1]);
logger.debug("key: {}, value: {}", keyValue[0], keyValue[1]);
Properties prefixProperties;
if (basePropretiesMap.containsKey(keyValue[0])) {
@ -249,6 +249,7 @@ public class JDBCInterpreter extends Interpreter {
private boolean existAccountInBaseProperty(String propertyKey) {
return basePropretiesMap.get(propertyKey).containsKey(USER_KEY) &&
!isEmpty((String) basePropretiesMap.get(propertyKey).get(USER_KEY)) &&
basePropretiesMap.get(propertyKey).containsKey(PASSWORD_KEY);
}
@ -295,7 +296,6 @@ public class JDBCInterpreter extends Interpreter {
}
}
jdbcUserConfigurations.setPropertyMap(propertyKey, basePropretiesMap.get(propertyKey));
if (existAccountInBaseProperty(propertyKey)) {
return;
}
@ -576,7 +576,7 @@ public class JDBCInterpreter extends Interpreter {
String precode = getProperty(String.format(PRECODE_KEY_TEMPLATE, propertyKey));
if (StringUtils.isNotBlank(precode)) {
precode = StringUtils.trim(precode);
logger.info("Run SQL precode '{}'", precode);
logger.debug("Run SQL precode '{}'", precode);
try (Statement statement = connection.createStatement()) {
statement.execute(precode);
if (!connection.getAutoCommit()) {
@ -720,7 +720,7 @@ public class JDBCInterpreter extends Interpreter {
@Override
public InterpreterResult interpret(String cmd, InterpreterContext contextInterpreter) {
logger.info("Run SQL command '{}'", cmd);
logger.debug("Run SQL command '{}'", cmd);
String propertyKey = getPropertyKey(cmd);
if (null != propertyKey && !propertyKey.equals(DEFAULT_KEY)) {
@ -728,8 +728,7 @@ public class JDBCInterpreter extends Interpreter {
}
cmd = cmd.trim();
logger.info("PropertyKey: {}, SQL command: '{}'", propertyKey, cmd);
logger.debug("PropertyKey: {}, SQL command: '{}'", propertyKey, cmd);
return executeSql(propertyKey, cmd, contextInterpreter);
}

View file

@ -339,18 +339,18 @@ public class JDBCInterpreterTest extends BasicJDBCTestCaseAdapter {
* 'jdbc1' interpreter has user('dbuser')/password('dbpassword') property
* 'jdbc2' interpreter doesn't have user/password property
* 'user1' doesn't have Credential information.
* 'user2' has 'jdbc2' Credential information that is same with database account.
* 'user2' has 'jdbc2' Credential information that is 'user2Id' / 'user2Pw' as id and password
*/
JDBCInterpreter jdbc1 = new JDBCInterpreter(getDBProperty("dbuser", "dbpassword"));
JDBCInterpreter jdbc2 = new JDBCInterpreter(getDBProperty(null, null));
JDBCInterpreter jdbc2 = new JDBCInterpreter(getDBProperty("", ""));
AuthenticationInfo user1Credential = getUserAuth("user1", null, null, null);
AuthenticationInfo user2Credential = getUserAuth("user2", "jdbc.jdbc2", "dbuser", "dbpassword");
AuthenticationInfo user2Credential = getUserAuth("user2", "jdbc.jdbc2", "user2Id","user2Pw");
// user1 runs jdbc1
jdbc1.open();
InterpreterContext ctx1 = new InterpreterContext("", "1", "jdbc.jdbc1", "", "", user1Credential,
InterpreterContext ctx1 = new InterpreterContext("", "1", "jdbc1", "", "", user1Credential,
null, null, null, null, null, null);
jdbc1.interpret("", ctx1);
@ -361,7 +361,7 @@ public class JDBCInterpreterTest extends BasicJDBCTestCaseAdapter {
// user1 runs jdbc2
jdbc2.open();
InterpreterContext ctx2 = new InterpreterContext("", "1", "jdbc.jdbc2", "", "", user1Credential,
InterpreterContext ctx2 = new InterpreterContext("", "1", "jdbc2", "", "", user1Credential,
null, null, null, null, null, null);
jdbc2.interpret("", ctx2);
@ -372,7 +372,7 @@ public class JDBCInterpreterTest extends BasicJDBCTestCaseAdapter {
// user2 runs jdbc1
jdbc1.open();
InterpreterContext ctx3 = new InterpreterContext("", "1", "jdbc.jdbc1", "", "", user2Credential,
InterpreterContext ctx3 = new InterpreterContext("", "1", "jdbc1", "", "", user2Credential,
null, null, null, null, null, null);
jdbc1.interpret("", ctx3);
@ -383,13 +383,13 @@ public class JDBCInterpreterTest extends BasicJDBCTestCaseAdapter {
// user2 runs jdbc2
jdbc2.open();
InterpreterContext ctx4 = new InterpreterContext("", "1", "jdbc.jdbc2", "", "", user2Credential,
InterpreterContext ctx4 = new InterpreterContext("", "1", "jdbc2", "", "", user2Credential,
null, null, null, null, null, null);
jdbc2.interpret("", ctx4);
JDBCUserConfigurations user2JDBC2Conf = jdbc2.getJDBCConfiguration("user2");
assertNull(user2JDBC2Conf.getPropertyMap("default").get("user"));
assertNull(user2JDBC2Conf.getPropertyMap("default").get("password"));
assertEquals("user2Id", user2JDBC2Conf.getPropertyMap("default").get("user"));
assertEquals("user2Pw", user2JDBC2Conf.getPropertyMap("default").get("password"));
jdbc2.close();
}

View file

@ -252,5 +252,10 @@ public class AngularObjectRegistry {
public void setRegistry(Map<String, Map<String, AngularObject>> registry) {
this.registry = registry;
for (Map<String, AngularObject> map : registry.values()) {
for (AngularObject ao : map.values()) {
ao.setListener(angularObjectListener);
}
}
}
}

View file

@ -46,7 +46,7 @@ import java.util.Map;
* RemoteInterpreterEventPoller is counter part in ZeppelinServer
*/
public class RemoteInterpreterEventClient implements ResourcePoolConnector {
private final Logger logger = LoggerFactory.getLogger(RemoteInterpreterEvent.class);
private final Logger logger = LoggerFactory.getLogger(RemoteInterpreterEventClient.class);
private final List<RemoteInterpreterEvent> eventQueue = new LinkedList<>();
private final List<ResourceSet> getAllResourceResponse = new LinkedList<>();
private final Map<ResourceId, Object> getResourceResponse = new HashMap<>();
@ -415,6 +415,7 @@ public class RemoteInterpreterEventClient implements ResourcePoolConnector {
}
private void sendEvent(RemoteInterpreterEvent event) {
logger.debug("Send Event: " + event);
synchronized (eventQueue) {
eventQueue.add(event);
eventQueue.notifyAll();
@ -446,7 +447,7 @@ public class RemoteInterpreterEventClient implements ResourcePoolConnector {
appendOutput.put("appId", appId);
appendOutput.put("type", type);
appendOutput.put("data", output);
logger.info("onAppoutputUpdate = {}", output);
logger.debug("onAppoutputUpdate = {}", output);
sendEvent(new RemoteInterpreterEvent(
RemoteInterpreterEventType.OUTPUT_UPDATE,
gson.toJson(appendOutput)));

View file

@ -124,6 +124,9 @@ public class RemoteInterpreterEventPoller extends Thread {
AngularObjectRegistry angularObjectRegistry = interpreterGroup.getAngularObjectRegistry();
try {
if (event.getType() != RemoteInterpreterEventType.NO_OP) {
logger.debug("Receive message from RemoteInterpreter Process: " + event.toString());
}
if (event.getType() == RemoteInterpreterEventType.NO_OP) {
continue;
} else if (event.getType() == RemoteInterpreterEventType.ANGULAR_OBJECT_ADD) {
@ -263,11 +266,20 @@ public class RemoteInterpreterEventPoller extends Thread {
logger.error("Can't handle event " + event, e);
}
}
try {
clearUnreadEvents(interpreterProcess.getClient());
} catch (Exception e1) {
logger.error("Can't get RemoteInterpreterEvent", e1);
}
if (appendFuture != null) {
appendFuture.cancel(true);
}
}
private void clearUnreadEvents(Client client) throws TException {
while (client.getEvent().getType() != RemoteInterpreterEventType.NO_OP) {}
}
private void progressRemoteZeppelinControlEvent(
RemoteZeppelinServerResource.Type resourceType,
RemoteInterpreterProcessListener remoteWorksEventListener,

View file

@ -0,0 +1,55 @@
/*
* 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.
*/
package org.apache.zeppelin.interpreter.remote;
import org.apache.zeppelin.interpreter.thrift.RemoteInterpreterEvent;
import org.apache.zeppelin.interpreter.thrift.RemoteInterpreterService;
import org.junit.Test;
import static org.apache.zeppelin.interpreter.thrift.RemoteInterpreterEventType.NO_OP;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class RemoteInterpreterEventPollerTest {
@Test
public void shouldClearUnreadEventsOnShutdown() throws Exception {
RemoteInterpreterProcess interpreterProc = getMockEventsInterpreterProcess();
RemoteInterpreterEventPoller eventPoller = new RemoteInterpreterEventPoller(null, null);
eventPoller.setInterpreterProcess(interpreterProc);
eventPoller.shutdown();
eventPoller.start();
eventPoller.join();
assertEquals(NO_OP, interpreterProc.getClient().getEvent().getType());
}
private RemoteInterpreterProcess getMockEventsInterpreterProcess() throws Exception {
RemoteInterpreterEvent fakeEvent = new RemoteInterpreterEvent();
RemoteInterpreterEvent noMoreEvents = new RemoteInterpreterEvent(NO_OP, "");
RemoteInterpreterService.Client client = mock(RemoteInterpreterService.Client.class);
RemoteInterpreterProcess intProc = mock(RemoteInterpreterProcess.class);
when(client.getEvent()).thenReturn(fakeEvent, fakeEvent, noMoreEvents);
when(intProc.getClient()).thenReturn(client);
return intProc;
}
}

View file

@ -494,7 +494,7 @@ public class NotebookServer extends WebSocketServlet
if (socketLists == null || socketLists.size() == 0) {
return;
}
LOG.debug("SEND >> " + m.op);
LOG.debug("SEND >> " + m);
for (NotebookSocket conn : socketLists) {
try {
conn.send(serializeMessage(m));
@ -512,7 +512,7 @@ public class NotebookServer extends WebSocketServlet
if (socketLists == null || socketLists.size() == 0) {
return;
}
LOG.debug("SEND >> " + m.op);
LOG.debug("SEND >> " + m);
for (NotebookSocket conn : socketLists) {
if (exclude.equals(conn)) {
continue;

View file

@ -1,5 +1,13 @@
{
"plugins": ["transform-object-rest-spread"],
"presets": ["es2015"]
"presets": [
[
"env",
{
"debug": true,
"targets": {
"browsers": ["last 5 version", "> 5%", "edge >= 12", "ie >= 9", "safari 7", "chrome 47", "firefox 31"]
}
}
]
]
}

View file

@ -2,16 +2,16 @@
"name": "zeppelin-web",
"version": "0.0.0",
"dependencies": {
"angular": "1.5.0",
"angular": "1.5.7",
"json3": "~3.3.1",
"es5-shim": "~3.1.0",
"bootstrap": "~3.2.0",
"angular-cookies": "1.5.0",
"angular-sanitize": "1.5.0",
"angular-animate": "1.5.0",
"angular-touch": "1.5.0",
"angular-route": "1.5.0",
"angular-resource": "1.5.0",
"angular-cookies": "1.5.7",
"angular-sanitize": "1.5.7",
"angular-animate": "1.5.7",
"angular-touch": "1.5.7",
"angular-route": "1.5.7",
"angular-resource": "1.5.7",
"angular-bootstrap": "~2.5.0",
"angular-websocket": "~1.0.13",
"ace-builds": "1.2.6",
@ -38,7 +38,7 @@
"ngclipboard": "^1.1.1"
},
"devDependencies": {
"angular-mocks": "1.5.0"
"angular-mocks": "1.5.7"
},
"appPath": "src",
"overrides": {

View file

@ -29,8 +29,7 @@
"babel-cli": "^6.18.0",
"babel-core": "^6.21.0",
"babel-loader": "^6.2.10",
"babel-plugin-transform-object-rest-spread": "^6.16.0",
"babel-preset-es2015": "^6.18.0",
"babel-preset-env": "^1.4.0",
"bower": "^1.8.0",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.26.1",

View file

@ -143,4 +143,8 @@ function HomeCtrl ($scope, noteListDataFactory, websocketMsgSrv, $rootScope, arr
$scope.getNoteName = function (note) {
return arrayOrderingSrv.getNoteName(note)
}
$scope.noteComparator = function (note1, note2) {
return arrayOrderingSrv.noteComparator(note1, note2)
}
}

View file

@ -40,16 +40,16 @@ limitations under the License.
<i style="font-size: 15px;" class="icon-notebook"></i> Create new note</a></h5>
<ul id="notebook-names">
<li class="filter-names" ng-include="'components/filterNoteNames/filter-note-names.html'"></li>
<li ng-repeat="note in home.notes.list | filter:query.q | orderBy:home.arrayOrderingSrv.noteListOrdering track by $index">
<li ng-repeat="note in home.notes.list | filter:query.q | orderBy:node:false:home.arrayOrderingSrv.noteComparator track by $index">
<i style="font-size: 10px;" class="icon-doc"></i>
<a style="text-decoration: none;" href="#/notebook/{{note.id}}">{{noteName(note)}}</a>
</li>
<div ng-if="!query.q || query.q === ''">
<li ng-repeat="node in home.notes.root.children | orderBy:home.arrayOrderingSrv.noteListOrdering track by $index"
<li ng-repeat="node in home.notes.root.children | orderBy:node:false:home.arrayOrderingSrv.noteComparator track by $index"
ng-include src="'app/home/notebook-template.html'" ng-class="note_folder_renderer"></li>
</div>
<div ng-if="query.q">
<li ng-repeat="node in home.notes.flatList| filter:query.q | orderBy:home.arrayOrderingSrv.noteListOrdering track by $index"
<li ng-repeat="node in home.notes.flatList| filter:query.q | orderBy:home.arrayOrderingSrv.noteFlatListOrdering track by $index"
ng-include src="'app/home/notebook-template.html'" ng-class="note_folder_renderer"></li>
</div>
</ul>

View file

@ -92,7 +92,7 @@ limitations under the License.
</div>
<div ng-if="!node.hidden">
<ul style="list-style-type: none; padding-left:15px;">
<li ng-repeat="node in node.children" ng-include="'app/home/notebook-template.html'" ng-class="'note_folder_renderer'"></li>
<li ng-repeat="node in node.children | orderBy:node:false:noteComparator" ng-include="'app/home/notebook-template.html'" ng-class="'note_folder_renderer'"></li>
</ul>
</div>
</div>
@ -116,7 +116,7 @@ limitations under the License.
</div>
<div ng-if="!node.hidden">
<ul style="list-style-type: none; padding-left:15px;">
<li ng-repeat="node in node.children" ng-include="'app/home/notebook-template.html'" ng-class="'note_folder_renderer'"></li>
<li ng-repeat="node in node.children | orderBy:node:false:noteComparator" ng-include="'app/home/notebook-template.html'" ng-class="'note_folder_renderer'"></li>
</ul>
</div>
</div>

View file

@ -28,11 +28,11 @@ limitations under the License.
<ul id="notebook-names">
<li class="filter-names" ng-include="'components/filterNoteNames/filter-note-names.html'"></li>
<div ng-if="!query.q || query.q === ''">
<li ng-repeat="node in home.notes.root.children | orderBy:home.arrayOrderingSrv.noteListOrdering track by $index"
<li ng-repeat="node in home.notes.root.children | orderBy:node:false:home.arrayOrderingSrv.noteComparator track by $index"
ng-include src="'app/home/notebook-template.html'" ng-class="note_folder_renderer"></li>
</div>
<div ng-if="query.q">
<li ng-repeat="node in home.notes.flatList | filter:query.q | orderBy:home.arrayOrderingSrv.noteListOrdering track by $index"
<li ng-repeat="node in home.notes.flatList | filter:query.q | orderBy:home.arrayOrderingSrv.noteFlatListOrdering track by $index"
ng-include src="'app/home/notebook-template.html'" ng-class="note_folder_renderer"></li>
</div>
</ul>

View file

@ -138,6 +138,15 @@ function ResultCtrl ($scope, $rootScope, $route, $window, $routeParams, $locatio
// queue for append output
const textResultQueueForAppend = []
// prevent body area scrollbar from blocking due to scroll in paragraph results
$scope.mouseOver = false
$scope.onMouseOver = function() { $scope.mouseOver = true }
$scope.onMouseOut = function() { $scope.mouseOver = false }
$scope.getPointerEvent = function() {
return ($scope.mouseOver) ? {'pointer-events': 'auto' }
: {'pointer-events': 'none' }
}
$scope.init = function (result, config, paragraph, index) {
// register helium plugin vis
let visBundles = heliumService.getVisualizationBundles()

View file

@ -15,17 +15,19 @@ limitations under the License.
<div>
<div ng-include src="'app/notebook/paragraph/result/result-chart-selector.html'"></div>
<div
ng-mouseout="onMouseOut()"
ng-mouseover="onMouseOver()"
id="p{{id}}_resize"
ng-if="!config.helium.activeApp"
style="padding-bottom: 5px;"
resize='{"allowresize": "{{!asIframe && !viewOnly}}", "graphType": "{{type}}"}'
resizable on-resize="resize(width, height);">
resizable on-resize="resize(width, height);">
<div ng-if="type=='TABLE'">
<div ng-if="type=='TABLE'"
ng-style="getPointerEvent()">
<!-- graph setting -->
<div class="option lightBold" style="overflow: visible;"
ng-show="graphMode!='table'
&& config.graph.optionOpen && !asIframe && !viewOnly">
ng-show="graphMode!='table' && 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>
@ -52,7 +54,8 @@ limitations under the License.
</div>
<div ng-if="type == 'TEXT'"
class="plainTextContainer">
class="plainTextContainer"
ng-style="getPointerEvent()">
<div class="fa fa-level-down scroll-paragraph-down"
ng-show="showScrollDownIcon()"
ng-click="scrollParagraphDown()"
@ -66,30 +69,40 @@ limitations under the License.
uib-tooltip="Scroll Top"></div>
</div>
<div id="p{{id}}_custom" class="resultContained"
ng-if="!isDefaultDisplay()">
<div id="p{{id}}_custom"
class="resultContained"
ng-if="!isDefaultDisplay()"
ng-style="getPointerEvent()">
</div>
<div id="p{{id}}_elem" class="resultContained"
ng-if="type == 'ELEMENT'">
<div id="p{{id}}_elem"
class="resultContained"
ng-if="type == 'ELEMENT'"
ng-style="getPointerEvent()">
</div>
<div id="p{{id}}_html" class="resultContained"
ng-if="type == 'HTML'">
<div id="p{{id}}_html"
class="resultContained"
ng-if="type == 'HTML'"
ng-style="getPointerEvent()">
</div>
<div id="p{{id}}_angular" class="resultContained"
ng-if="type == 'ANGULAR'">
<div id="p{{id}}_angular"
class="resultContained"
ng-if="type == 'ANGULAR'"
ng-style="getPointerEvent()">
</div>
<img id="{{id}}_img"
ng-if="type == 'IMG'"
ng-src="{{getBase64ImageSrc(result.data)}}" />
ng-src="{{getBase64ImageSrc(result.data)}}"
ng-style="getPointerEvent()" />
</div>
<div ng-repeat="app in apps">
<div id="p{{app.id}}"
ng-show="config.helium.activeApp == app.id">
ng-show="config.helium.activeApp == app.id"
ng-style="getPointerEvent()">
</div>
</div>
</div>

View file

@ -33,4 +33,30 @@ function arrayOrderingSrv (TRASH_FOLDER_ID) {
return note.name
}
}
this.noteComparator = function (v1, v2) {
let note1 = v1.value
let note2 = v2.value
if (note1.id === TRASH_FOLDER_ID) {
return 1
}
if (note2.id === TRASH_FOLDER_ID) {
return -1
}
if (note1.children === undefined && note2.children !== undefined) {
return 1
}
if (note1.children !== undefined && note2.children === undefined) {
return -1
}
let noteName1 = arrayOrderingSrv.getNoteName(note1)
let noteName2 = arrayOrderingSrv.getNoteName(note2)
return noteName1.localeCompare(noteName2)
}
}

View file

@ -33,7 +33,7 @@ limitations under the License.
</div>
<div class="expandable" style="color: black;">
<ul>
<li ng-repeat="note in note.children | orderBy:navbar.arrayOrderingSrv.noteListOrdering track by $index"
<li ng-repeat="note in note.children | orderBy:node:false:navbar.arrayOrderingSrv.noteComparator track by $index"
ng-class="{'active' : navbar.isActive(note.id)}"
ng-include="'components/navbar/navbar-noteList-elem.html'">
</li>

View file

@ -25,20 +25,20 @@ limitations under the License.
<div class="collapse navbar-collapse" ng-controller="NavCtrl as navbar">
<ul class="nav navbar-nav" ng-if="ticket">
<li class="dropdown notebook-list-dropdown" dropdown>
<a href="#" class="dropdown-toggle" data-toggle="dropdown" dropdown-toggle>Notebook <span class="caret"></span></a>
<li class="dropdown notebook-list-dropdown" uib-dropdown>
<a href="#" class="dropdown-toggle" data-toggle="dropdown" uib-dropdown-toggle>Notebook <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li ng-controller="NotenameCtrl as notenamectrl"><a href="" data-toggle="modal" data-target="#noteNameModal" ng-click="notenamectrl.getInterpreterSettings()"><i class="fa fa-plus"></i> Create new note</a></li>
<li class="divider"></li>
<div id="notebook-list" class="scrollbar-container" ng-if="isDrawNavbarNoteList">
<li class="filter-names" ng-include="'components/filterNoteNames/filter-note-names.html'"></li>
<div ng-if="!query.q || query.q === ''">
<li ng-repeat="note in navbar.notes.root.children | orderBy:navbar.arrayOrderingSrv.noteListOrdering track by note.id"
<li ng-repeat="note in navbar.notes.root.children | orderBy:node:false:navbar.arrayOrderingSrv.noteComparator track by note.id"
ng-class="{'active' : navbar.isActive(note.id)}" ng-include="'components/navbar/navbar-noteList-elem.html'">
</li>
</div>
<div ng-if="query.q">
<li ng-repeat="note in navbar.notes.flatList | filter : query.q | orderBy:navbar.arrayOrderingSrv.noteListOrdering track by note.id"
<li ng-repeat="note in navbar.notes.flatList | filter : query.q | orderBy:navbar.arrayOrderingSrv.noteFlatListOrdering track by note.id"
ng-class="{'active' : navbar.isActive(note.id)}" ng-include="'components/navbar/navbar-noteList-elem.html'">
</li>
</div>

View file

@ -14,8 +14,8 @@
angular.module('zeppelinWebApp').directive('popoverHtmlUnsafe', popoverHtmlUnsafe)
function popoverHtmlUnsafe ($tooltip) {
function popoverHtmlUnsafe ($uibTooltip) {
'ngInject'
return $tooltip('popoverHtmlUnsafe', 'popover', 'click')
return $uibTooltip('popoverHtmlUnsafe', 'popover', 'click')
}

View file

@ -32,6 +32,7 @@ import java.net.URL;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* This registry reads helium package json data
@ -55,7 +56,10 @@ public class HeliumOnlineRegistry extends HeliumRegistry {
public HeliumOnlineRegistry(String name, String uri, File registryCacheDir) {
super(name, uri);
registryCacheDir.mkdirs();
this.registryCacheFile = new File(registryCacheDir, name);
UUID registryCacheFileUuid = UUID.nameUUIDFromBytes(uri.getBytes());
this.registryCacheFile = new File(registryCacheDir, registryCacheFileUuid.toString());
gson = new Gson();
}

View file

@ -11,8 +11,7 @@ DEPENDENCIES
"webpack": "^1.12.2",
"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-env": "^1.4.0",
"css-loader": "^0.26.2",
"style-loader": "^0.13.2",
"url-loader": "^0.5.8",

View file

@ -24,7 +24,18 @@ module.exports = {
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules\/(?!(zeppelin-spell|zeppelin-vis|zeppelin-tabledata)\/).*/,
query: { presets: ['es2015', 'stage-0'] },
query: {
presets: [
[
"env",
{
"targets": {
"browsers": ["last 5 version", "> 5%", "edge >= 12", "ie >= 9", "safari 7", "chrome 47", "firefox 31"]
}
}
]
]
},
},
{ test: /(\.css)$/, loaders: ['style', 'css?sourceMap&importLoaders=1'], },
{ test: /\.woff(\?\S*)?$/, loader: 'url-loader?limit=10000&minetype=application/font-woff', },