[ZEPPELIN-1363] note dynamic forms (simple; native: spark, python)

This commit is contained in:
tinkoff-dwh 2017-10-26 12:09:27 +05:00
parent 1a79b51d55
commit c566462a5f
81 changed files with 1072 additions and 276 deletions

View file

@ -24,9 +24,10 @@ limitations under the License.
<div id="toc"></div>
Apache Zeppelin dynamically creates input forms. Depending on language backend, there're two different ways to create dynamic form.
Custom language backend can select which type of form creation it wants to use.
Custom language backend can select which type of form creation it wants to use. Forms can have different scope (paragraph or note).
Forms with scope "note" available in all paragraphs regardless of which paragraph has code to create these forms.
## Using form Templates
## Using form Templates (scope: paragraph)
This mode creates form using simple template language. It's simple and easy to use. For example Markdown, Shell, Spark SQL language backend uses it.
@ -81,7 +82,11 @@ Even if you uncheck this option, still you can run it by pressing `Enter`.
<img src="{{BASE_PATH}}/assets/themes/zeppelin/img/screenshots/selectForm-checkbox.png" />
## Creates Programmatically
## Using form Templates (scope: note)
Has a same syntax but starts with two symbols `$`. (for ex. input `$${forName}`)
## Creates Programmatically (scope: paragraph)
Some language backends can programmatically create forms. For example [ZeppelinContext](../../interpreter/spark.html#zeppelincontext) provides a form creation API
@ -93,7 +98,7 @@ Here are some examples:
{% highlight scala %}
%spark
println("Hello "+z.input("name"))
println("Hello "+z.textbox("name"))
{% endhighlight %}
</div>
@ -101,7 +106,7 @@ println("Hello "+z.input("name"))
{% highlight python %}
%pyspark
print("Hello "+z.input("name"))
print("Hello "+z.textbox("name"))
{% endhighlight %}
</div>
@ -114,7 +119,7 @@ print("Hello "+z.input("name"))
{% highlight scala %}
%spark
println("Hello "+z.input("name", "sun"))
println("Hello "+z.textbox("name", "sun"))
{% endhighlight %}
</div>
@ -122,7 +127,7 @@ println("Hello "+z.input("name", "sun"))
{% highlight python %}
%pyspark
print("Hello "+z.input("name", "sun"))
print("Hello "+z.textbox("name", "sun"))
{% endhighlight %}
</div>
@ -184,3 +189,27 @@ print("Hello "+ " and ".join(z.checkbox("fruit", options, ["apple"])))
</div>
</div>
<img src="{{BASE_PATH}}/assets/themes/zeppelin/img/screenshots/form_checkbox_prog.png" />
## Creates Programmatically (scope: note)
The difference in the method names:
<table class="table-configuration">
<tr>
<th>Scope paragraph</th>
<th>Scope note</th>
</tr>
<tr>
<td>input (or textbox)</td>
<td>noteTextbox</td>
</tr>
<tr>
<td>select</td>
<td>noteSelect</td>
</tr>
<tr>
<td>checkbox</td>
<td>noteCheckbox</td>
</tr>
</table>

View file

@ -164,8 +164,8 @@ public class ElasticsearchInterpreterTest {
private InterpreterContext buildContext(String noteAndParagraphId) {
final AngularObjectRegistry angularObjReg = new AngularObjectRegistry("elasticsearch", null);
return new InterpreterContext(noteAndParagraphId, noteAndParagraphId, null, null, null, null, null,
null, angularObjReg , null, null, null);
return new InterpreterContext(noteAndParagraphId, noteAndParagraphId, null, null, null, null,
null, null, null, angularObjReg , null, null, null);
}
@Theory

View file

@ -40,7 +40,7 @@ public class FlinkInterpreterTest {
Properties p = new Properties();
flink = new FlinkInterpreter(p);
flink.open();
context = new InterpreterContext(null, null, null, null, null, null, null, null, null, null, null, null);
context = new InterpreterContext(null, null, null, null, null, null, null, null, null, null, null, null, null);
}
@AfterClass

View file

@ -40,7 +40,7 @@ public class IgniteInterpreterTest {
private static final String HOST = "127.0.0.1:47500..47509";
private static final InterpreterContext INTP_CONTEXT =
new InterpreterContext(null, null, null, null, null, null, null, null, null, null, null, null);
new InterpreterContext(null, null, null, null, null, null, null, null, null, null, null, null, null);
private IgniteInterpreter intp;
private Ignite ignite;

View file

@ -44,7 +44,7 @@ public class IgniteSqlInterpreterTest {
private static final String HOST = "127.0.0.1:47500..47509";
private static final InterpreterContext INTP_CONTEXT =
new InterpreterContext(null, null, null, null, null, null, null, null, null, null, null, null);
new InterpreterContext(null, null, null, null, null, null, null, null, null, null, null, null, null);
private Ignite ignite;
private IgniteSqlInterpreter intp;

View file

@ -91,8 +91,8 @@ public class JDBCInterpreterTest extends BasicJDBCTestCaseAdapter {
PreparedStatement insertStatement = connection.prepareStatement("insert into test_table(id, name) values ('a', 'a_name'),('b', 'b_name'),('c', ?);");
insertStatement.setString(1, null);
insertStatement.execute();
interpreterContext = new InterpreterContext("", "1", null, "", "", new AuthenticationInfo("testUser"), null, null, null, null,
null, null);
interpreterContext = new InterpreterContext("", "1", null, "", "",
new AuthenticationInfo("testUser"), null, null, null,null, null, null, null);
}
@ -418,7 +418,7 @@ public class JDBCInterpreterTest extends BasicJDBCTestCaseAdapter {
// user1 runs jdbc1
jdbc1.open();
InterpreterContext ctx1 = new InterpreterContext("", "1", "jdbc1", "", "", user1Credential,
null, null, null, null, null, null);
null, null, null, null, null, null, null);
jdbc1.interpret("", ctx1);
JDBCUserConfigurations user1JDBC1Conf = jdbc1.getJDBCConfiguration("user1");
@ -429,7 +429,7 @@ public class JDBCInterpreterTest extends BasicJDBCTestCaseAdapter {
// user1 runs jdbc2
jdbc2.open();
InterpreterContext ctx2 = new InterpreterContext("", "1", "jdbc2", "", "", user1Credential,
null, null, null, null, null, null);
null, null, null, null, null, null, null);
jdbc2.interpret("", ctx2);
JDBCUserConfigurations user1JDBC2Conf = jdbc2.getJDBCConfiguration("user1");
@ -440,7 +440,7 @@ public class JDBCInterpreterTest extends BasicJDBCTestCaseAdapter {
// user2 runs jdbc1
jdbc1.open();
InterpreterContext ctx3 = new InterpreterContext("", "1", "jdbc1", "", "", user2Credential,
null, null, null, null, null, null);
null, null, null, null, null, null, null);
jdbc1.interpret("", ctx3);
JDBCUserConfigurations user2JDBC1Conf = jdbc1.getJDBCConfiguration("user2");
@ -451,7 +451,7 @@ public class JDBCInterpreterTest extends BasicJDBCTestCaseAdapter {
// user2 runs jdbc2
jdbc2.open();
InterpreterContext ctx4 = new InterpreterContext("", "1", "jdbc2", "", "", user2Credential,
null, null, null, null, null, null);
null, null, null, null, null, null, null);
jdbc2.interpret("", ctx4);
JDBCUserConfigurations user2JDBC2Conf = jdbc2.getJDBCConfiguration("user2");

View file

@ -90,7 +90,7 @@ public class LivyInterpreterIT {
MyInterpreterOutputListener outputListener = new MyInterpreterOutputListener();
InterpreterOutput output = new InterpreterOutput(outputListener);
final InterpreterContext context = new InterpreterContext("noteId", "paragraphId", "livy.spark",
"title", "text", authInfo, null, null, null, null, null, output);
"title", "text", authInfo, null, null, null, null, null, null, output);
sparkInterpreter.open();
try {
@ -211,7 +211,7 @@ public class LivyInterpreterIT {
MyInterpreterOutputListener outputListener = new MyInterpreterOutputListener();
InterpreterOutput output = new InterpreterOutput(outputListener);
InterpreterContext context = new InterpreterContext("noteId", "paragraphId", "livy.spark",
"title", "text", authInfo, null, null, null, null, null, output);
"title", "text", authInfo, null, null, null, null, null, null, output);
sparkInterpreter.open();
LivySparkSQLInterpreter sqlInterpreter = new LivySparkSQLInterpreter(properties);
@ -307,7 +307,7 @@ public class LivyInterpreterIT {
MyInterpreterOutputListener outputListener = new MyInterpreterOutputListener();
InterpreterOutput output = new InterpreterOutput(outputListener);
InterpreterContext context = new InterpreterContext("noteId", "paragraphId", "livy.sql",
"title", "text", authInfo, null, null, null, null, null, output);
"title", "text", authInfo, null, null, null, null, null, null, output);
InterpreterResult result = sqlInterpreter.interpret("show tables", context);
assertEquals(InterpreterResult.Code.SUCCESS, result.code());
assertEquals(InterpreterResult.Type.TABLE, result.message().get(0).getType());
@ -334,7 +334,7 @@ public class LivyInterpreterIT {
MyInterpreterOutputListener outputListener = new MyInterpreterOutputListener();
InterpreterOutput output = new InterpreterOutput(outputListener);
final InterpreterContext context = new InterpreterContext("noteId", "paragraphId", "livy.spark",
"title", "text", authInfo, null, null, null, null, null, output);
"title", "text", authInfo, null, null, null, null, null, null, output);
sparkInterpreter.open();
final LivySparkSQLInterpreter sqlInterpreter = new LivySparkSQLInterpreter(properties);
@ -415,7 +415,7 @@ public class LivyInterpreterIT {
MyInterpreterOutputListener outputListener = new MyInterpreterOutputListener();
InterpreterOutput output = new InterpreterOutput(outputListener);
InterpreterContext context = new InterpreterContext("noteId", "paragraphId", "livy.spark",
"title", "text", authInfo, null, null, null, null, null, output);
"title", "text", authInfo, null, null, null, null, null, null, output);
sparkInterpreter.open();
LivySparkSQLInterpreter sqlInterpreter = new LivySparkSQLInterpreter(properties);
@ -481,7 +481,7 @@ public class LivyInterpreterIT {
MyInterpreterOutputListener outputListener = new MyInterpreterOutputListener();
InterpreterOutput output = new InterpreterOutput(outputListener);
InterpreterContext context = new InterpreterContext("noteId", "paragraphId", "livy.spark",
"title", "text", authInfo, null, null, null, null, null, output);
"title", "text", authInfo, null, null, null, null, null, null, output);
sparkInterpreter.open();
LivySparkSQLInterpreter sqlInterpreter = new LivySparkSQLInterpreter(newProps);
@ -538,7 +538,7 @@ public class LivyInterpreterIT {
MyInterpreterOutputListener outputListener = new MyInterpreterOutputListener();
InterpreterOutput output = new InterpreterOutput(outputListener);
final InterpreterContext context = new InterpreterContext("noteId", "paragraphId", "livy.pyspark",
"title", "text", authInfo, null, null, null, null, null, output);
"title", "text", authInfo, null, null, null, null, null, null, output);
pysparkInterpreter.open();
// test traceback msg
@ -665,7 +665,7 @@ public class LivyInterpreterIT {
MyInterpreterOutputListener outputListener = new MyInterpreterOutputListener();
InterpreterOutput output = new InterpreterOutput(outputListener);
InterpreterContext context = new InterpreterContext("noteId", "paragraphId", "livy.spark",
"title", "text", authInfo, null, null, null, null, null, output);
"title", "text", authInfo, null, null, null, null, null, null, output);
sparkInterpreter.open();
try {
@ -703,7 +703,7 @@ public class LivyInterpreterIT {
MyInterpreterOutputListener outputListener = new MyInterpreterOutputListener();
InterpreterOutput output = new InterpreterOutput(outputListener);
final InterpreterContext context = new InterpreterContext("noteId", "paragraphId", "livy.sparkr",
"title", "text", authInfo, null, null, null, null, null, output);
"title", "text", authInfo, null, null, null, null, null, null, output);
sparkRInterpreter.open();
try {
@ -780,7 +780,7 @@ public class LivyInterpreterIT {
MyInterpreterOutputListener outputListener = new MyInterpreterOutputListener();
InterpreterOutput output = new InterpreterOutput(outputListener);
InterpreterContext context = new InterpreterContext("noteId", "paragraphId", "livy.sql",
"title", "text", authInfo, null, null, null, null, null, output);
"title", "text", authInfo, null, null, null, null, null, null, output);
String p1 = IOUtils.toString(getClass().getResourceAsStream("/livy_tutorial_1.scala"));
InterpreterResult result = sparkInterpreter.interpret(p1, context);

View file

@ -93,6 +93,7 @@ public class Neo4jCypherInterpreterTest {
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new GUI(),
new AngularObjectRegistry(new InterpreterGroup().getId(), null),
new LocalResourcePool("id"),
new LinkedList<InterpreterContextRunner>(),

View file

@ -44,8 +44,8 @@ public class PigInterpreterSparkTest {
properties.put("zeppelin.pig.includeJobStats", includeJobStats + "");
pigInterpreter = new PigInterpreter(properties);
pigInterpreter.open();
context = new InterpreterContext(null, "paragraph_id", null, null, null, null, null, null, null, null,
null, null);
context = new InterpreterContext(null, "paragraph_id", null, null, null, null, null, null, null,
null, null, null, null);
}
@After

View file

@ -47,8 +47,8 @@ public class PigInterpreterTest {
properties.put("zeppelin.pig.includeJobStats", includeJobStats + "");
pigInterpreter = new PigInterpreter(properties);
pigInterpreter.open();
context = new InterpreterContext(null, "paragraph_id", null, null, null, null, null, null, null, null,
null, null);
context = new InterpreterContext(null, "paragraph_id", null, null, null,
null, null, null, null, null, null,null, null);
}
@After

View file

@ -48,8 +48,8 @@ public class PigInterpreterTezTest {
properties.put("tez.queue.name", "test");
pigInterpreter = new PigInterpreter(properties);
pigInterpreter.open();
context = new InterpreterContext(null, "paragraph_id", null, null, null, null, null, null, null, null,
null, null);
context = new InterpreterContext(null, "paragraph_id", null, null, null, null, null, null, null,
null, null, null, null);
}
@After

View file

@ -66,8 +66,8 @@ public class PigQueryInterpreterTest {
pigInterpreter.open();
pigQueryInterpreter.open();
context = new InterpreterContext(null, "paragraph_id", null, null, null, null, null, null, null, null,
null, null);
context = new InterpreterContext(null, "paragraph_id", null, null, null, null, null, null, null,
null, null, null, null);
}
@After

View file

@ -303,6 +303,7 @@ public class IPythonInterpreter extends Interpreter implements ExecuteResultHand
@Override
public InterpreterResult interpret(String st, InterpreterContext context) {
zeppelinContext.setGui(context.getGui());
zeppelinContext.setNoteGui(context.getNoteGui());
interpreterOutput.setInterpreterOutput(context.out);
ExecuteResponse response =
ipythonClient.stream_execute(ExecuteRequest.newBuilder().setCode(st).build(),

View file

@ -69,6 +69,7 @@ public class PythonInterpreter extends Interpreter implements ExecuteResultHandl
public static final String DEFAULT_ZEPPELIN_PYTHON = "python";
public static final String MAX_RESULT = "zeppelin.python.maxResult";
private PythonZeppelinContext zeppelinContext;
private InterpreterContext context;
private Pattern errorInLastLine = Pattern.compile(".*(Error|Exception): .*$");
private String pythonPath;
@ -223,6 +224,9 @@ public class PythonInterpreter extends Interpreter implements ExecuteResultHandl
// try IPythonInterpreter first. If it is not available, we will fallback to the original
// python interpreter implementation.
iPythonInterpreter = getIPythonInterpreter();
this.zeppelinContext = new PythonZeppelinContext(
getInterpreterGroup().getInterpreterHookRegistry(),
Integer.parseInt(getProperty("zeppelin.python.maxResult", "1000")));
if (getProperty("zeppelin.python.useIPython", "true").equals("true") &&
iPythonInterpreter.checkIPythonPrerequisite()) {
try {
@ -374,12 +378,16 @@ public class PythonInterpreter extends Interpreter implements ExecuteResultHandl
if (iPythonInterpreter != null) {
return iPythonInterpreter.interpret(cmd, contextInterpreter);
}
if (cmd == null || cmd.isEmpty()) {
return new InterpreterResult(Code.SUCCESS, "");
}
this.context = contextInterpreter;
zeppelinContext.setGui(context.getGui());
zeppelinContext.setNoteGui(context.getNoteGui());
if (!pythonscriptRunning) {
return new InterpreterResult(Code.ERROR, "python process not running"
+ outputStream.toString());
@ -559,8 +567,8 @@ public class PythonInterpreter extends Interpreter implements ExecuteResultHandl
}
}
public GUI getGui() {
return context.getGui();
public PythonZeppelinContext getZeppelinContext() {
return zeppelinContext;
}
String getLocalIp() {

View file

@ -34,26 +34,39 @@ class PyZeppelinContext(object):
self.max_result = z.getMaxResult()
def input(self, name, defaultValue=""):
return self.z.getGui().input(name, defaultValue)
return self.z.input(name, defaultValue)
def textbox(self, name, defaultValue=""):
return self.z.textbox(name, defaultValue)
def noteTextbox(self, name, defaultValue=""):
return self.z.noteTextbox(name, defaultValue)
def select(self, name, options, defaultValue=""):
javaOptions = gateway.new_array(self.paramOption, len(options))
i = 0
for tuple in options:
javaOptions[i] = self.paramOption(tuple[0], tuple[1])
i += 1
return self.z.getGui().select(name, defaultValue, javaOptions)
return self.z.select(name, defaultValue, self.getParamOptions(options))
def noteSelect(self, name, options, defaultValue=""):
return self.z.noteSelect(name, defaultValue, self.getParamOptions(options))
def checkbox(self, name, options, defaultChecked=[]):
return self.z.checkbox(name, self.getDefaultChecked(defaultChecked), self.getParamOptions(options))
def noteCheckbox(self, name, options, defaultChecked=[]):
return self.z.noteCheckbox(name, self.getDefaultChecked(defaultChecked), self.getParamOptions(options))
def getParamOptions(self, options):
javaOptions = gateway.new_array(self.paramOption, len(options))
i = 0
for tuple in options:
javaOptions[i] = self.paramOption(tuple[0], tuple[1])
i += 1
javaDefaultCheck = self.javaList()
return javaOptions
def getDefaultChecked(self, defaultChecked):
javaDefaultChecked = self.javaList()
for check in defaultChecked:
javaDefaultCheck.append(check)
return self.z.getGui().checkbox(name, javaDefaultCheck, javaOptions)
javaDefaultChecked.append(check)
return javaDefaultChecked
def show(self, p, **kwargs):
if type(p).__name__ == "DataFrame": # does not play well with sub-classes

View file

@ -64,26 +64,39 @@ class PyZeppelinContext(object):
return self.z.getCurrentInterpreterContext()
def input(self, name, defaultValue=""):
return self.z.getGui().input(name, defaultValue)
return self.z.input(name, defaultValue)
def textbox(self, name, defaultValue=""):
return self.z.textbox(name, defaultValue)
def noteTextbox(self, name, defaultValue=""):
return self.z.noteTextbox(name, defaultValue)
def select(self, name, options, defaultValue=""):
javaOptions = gateway.new_array(self.paramOption, len(options))
i = 0
for tuple in options:
javaOptions[i] = self.paramOption(tuple[0], tuple[1])
i += 1
return self.z.getGui().select(name, defaultValue, javaOptions)
return self.z.select(name, defaultValue, self.getParamOptions(options))
def noteSelect(self, name, options, defaultValue=""):
return self.z.noteSelect(name, defaultValue, self.getParamOptions(options))
def checkbox(self, name, options, defaultChecked=[]):
return self.z.checkbox(name, self.getDefaultChecked(defaultChecked), self.getParamOptions(options))
def noteCheckbox(self, name, options, defaultChecked=[]):
return self.z.noteCheckbox(name, self.getDefaultChecked(defaultChecked), self.getParamOptions(options))
def getParamOptions(self, options):
javaOptions = gateway.new_array(self.paramOption, len(options))
i = 0
for tuple in options:
javaOptions[i] = self.paramOption(tuple[0], tuple[1])
i += 1
javaDefaultCheck = self.javaList()
return javaOptions
def getDefaultChecked(self, defaultChecked):
javaDefaultChecked = self.javaList()
for check in defaultChecked:
javaDefaultCheck.append(check)
return self.z.getGui().checkbox(name, javaDefaultCheck, javaOptions)
javaDefaultChecked.append(check)
return javaDefaultChecked
def show(self, p, **kwargs):
if hasattr(p, '__name__') and p.__name__ == "matplotlib.pyplot":
@ -206,7 +219,7 @@ intp = gateway.entry_point
intp.onPythonScriptInitialized(os.getpid())
java_import(gateway.jvm, "org.apache.zeppelin.display.Input")
z = __zeppelin__ = PyZeppelinContext(intp)
z = __zeppelin__ = PyZeppelinContext(intp.getZeppelinContext())
__zeppelin__._setup_matplotlib()
_zcUserQueryNameSpace["__zeppelin__"] = __zeppelin__

View file

@ -411,6 +411,7 @@ public class IPythonInterpreterTest {
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new GUI(),
null,
null,
null,

View file

@ -131,6 +131,7 @@ public class PythonCondaInterpreterTest {
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new GUI(),
null,
null,
null,

View file

@ -86,6 +86,7 @@ public class PythonDockerInterpreterTest {
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new GUI(),
null,
null,
null,

View file

@ -71,6 +71,7 @@ public class PythonInterpreterMatplotlibTest implements InterpreterOutputListene
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new GUI(),
new AngularObjectRegistry(intpGroup.getId(), null),
new LocalResourcePool("id"),
new LinkedList<InterpreterContextRunner>(),

View file

@ -83,6 +83,7 @@ public class PythonInterpreterPandasSqlTest implements InterpreterOutputListener
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new GUI(),
new AngularObjectRegistry(intpGroup.getId(), null),
new LocalResourcePool("id"),
new LinkedList<InterpreterContextRunner>(),

View file

@ -83,6 +83,7 @@ public class PythonInterpreterTest implements InterpreterOutputListener {
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new GUI(),
new AngularObjectRegistry(group.getId(), null),
new LocalResourcePool("id"),
new LinkedList<InterpreterContextRunner>(),

View file

@ -65,7 +65,7 @@ public class ScaldingInterpreterTest {
InterpreterGroup intpGroup = new InterpreterGroup();
context = new InterpreterContext("note", "id", null, "title", "text", new AuthenticationInfo(),
new HashMap<String, Object>(), new GUI(), new AngularObjectRegistry(
new HashMap<String, Object>(), new GUI(), new GUI(), new AngularObjectRegistry(
intpGroup.getId(), null), null,
new LinkedList<InterpreterContextRunner>(), null);
}

View file

@ -44,6 +44,7 @@ public class ScioInterpreterTest {
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new GUI(),
new AngularObjectRegistry(intpGroup.getId(), null),
new LocalResourcePool("id"),
new LinkedList<InterpreterContextRunner>(),

View file

@ -41,7 +41,8 @@ public class ShellInterpreterTest {
p.setProperty("shell.command.timeout.millisecs", "2000");
shell = new ShellInterpreter(p);
context = new InterpreterContext("", "1", null, "", "", null, null, null, null, null, null, null);
context = new InterpreterContext("", "1", null, "", "", null, null, null, null, null, null,
null, null);
shell.open();
}

View file

@ -464,6 +464,7 @@ public class PySparkInterpreter extends Interpreter implements ExecuteResultHand
SparkZeppelinContext __zeppelin__ = sparkInterpreter.getZeppelinContext();
__zeppelin__.setInterpreterContext(context);
__zeppelin__.setGui(context.getGui());
__zeppelin__.setNoteGui(context.getNoteGui());
pythonInterpretRequest = new PythonInterpretRequest(st, jobGroup, jobDesc);
statementOutput = null;

View file

@ -1144,6 +1144,7 @@ public class SparkInterpreter extends Interpreter {
public InterpreterResult interpret(String[] lines, InterpreterContext context) {
synchronized (this) {
z.setGui(context.getGui());
z.setNoteGui(context.getNoteGui());
String jobDesc = "Started by: " + Utils.getUserName(context.getAuthenticationInfo());
sc.setJobGroup(Utils.buildJobGroupId(context), jobDesc, false);
InterpreterResult r = interpretInput(lines, context);

View file

@ -33,7 +33,6 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import static scala.collection.JavaConversions.asJavaCollection;
import static scala.collection.JavaConversions.asJavaIterable;
import static scala.collection.JavaConversions.collectionAsScalaIterable;
@ -205,9 +204,44 @@ public class SparkZeppelinContext extends BaseZeppelinContext {
String name,
scala.collection.Iterable<Object> defaultChecked,
scala.collection.Iterable<Tuple2<Object, String>> options) {
return scala.collection.JavaConversions.asScalaBuffer(
gui.checkbox(name, asJavaCollection(defaultChecked),
tuplesToParamOptions(options))).toSeq();
List<Object> defaultCheckedList = Lists.newArrayList(asJavaIterable(defaultChecked).iterator());
Collection<Object> checkbox = checkbox(name, defaultCheckedList, tuplesToParamOptions(options));
List<Object> checkboxList = Arrays.asList(checkbox.toArray());
return scala.collection.JavaConversions.asScalaBuffer(checkboxList).toSeq();
}
@ZeppelinApi
public Object noteSelect(String name, scala.collection.Iterable<Tuple2<Object, String>> options) {
return noteSelect(name, "", options);
}
@ZeppelinApi
public Object noteSelect(String name, Object defaultValue,
scala.collection.Iterable<Tuple2<Object, String>> options) {
return noteSelect(name, defaultValue, tuplesToParamOptions(options));
}
@ZeppelinApi
public scala.collection.Seq<Object> noteCheckbox(
String name,
scala.collection.Iterable<Tuple2<Object, String>> options) {
List<Object> allChecked = new LinkedList<>();
for (Tuple2<Object, String> option : asJavaIterable(options)) {
allChecked.add(option._1());
}
return noteCheckbox(name, collectionAsScalaIterable(allChecked), options);
}
@ZeppelinApi
public scala.collection.Seq<Object> noteCheckbox(
String name,
scala.collection.Iterable<Object> defaultChecked,
scala.collection.Iterable<Tuple2<Object, String>> options) {
List<Object> defaultCheckedList = Lists.newArrayList(asJavaIterable(defaultChecked).iterator());
Collection<Object> checkbox = noteCheckbox(name, defaultCheckedList,
tuplesToParamOptions(options));
List<Object> checkboxList = Arrays.asList(checkbox.toArray());
return scala.collection.JavaConversions.asScalaBuffer(checkboxList).toSeq();
}
private OptionInput.ParamOption[] tuplesToParamOptions(

View file

@ -81,24 +81,46 @@ class PyZeppelinContext(dict):
def input(self, name, defaultValue=""):
return self.z.input(name, defaultValue)
def textbox(self, name, defaultValue=""):
return self.z.textbox(name, defaultValue)
def noteTextbox(self, name, defaultValue=""):
return self.z.noteTextbox(name, defaultValue)
def select(self, name, options, defaultValue=""):
# auto_convert to ArrayList doesn't match the method signature on JVM side
tuples = list(map(lambda items: self.__tupleToScalaTuple2(items), options))
iterables = gateway.jvm.scala.collection.JavaConversions.collectionAsScalaIterable(tuples)
return self.z.select(name, defaultValue, iterables)
return self.z.select(name, defaultValue, self.getParamOptions(options))
def noteSelect(self, name, options, defaultValue=""):
return self.z.noteSelect(name, defaultValue, self.getParamOptions(options))
def checkbox(self, name, options, defaultChecked=None):
if defaultChecked is None:
defaultChecked = []
optionTuples = list(map(lambda items: self.__tupleToScalaTuple2(items), options))
optionIterables = gateway.jvm.scala.collection.JavaConversions.collectionAsScalaIterable(optionTuples)
defaultCheckedIterables = gateway.jvm.scala.collection.JavaConversions.collectionAsScalaIterable(defaultChecked)
checkedItems = gateway.jvm.scala.collection.JavaConversions.seqAsJavaList(self.z.checkbox(name, defaultCheckedIterables, optionIterables))
optionsIterable = self.getParamOptions(options)
defaultCheckedIterables = self.getDefaultChecked(defaultChecked)
checkedItems = gateway.jvm.scala.collection.JavaConversions.seqAsJavaList(self.z.checkbox(name, defaultCheckedIterables, optionsIterable))
result = []
for checkedItem in checkedItems:
result.append(checkedItem)
return result;
def noteCheckbox(self, name, options, defaultChecked=None):
optionsIterable = self.getParamOptions(options)
defaultCheckedIterables = self.getDefaultChecked(defaultChecked)
checkedItems = gateway.jvm.scala.collection.JavaConversions.seqAsJavaList(self.z.noteCheckbox(name, defaultCheckedIterables, optionsIterable))
result = []
for checkedItem in checkedItems:
result.append(checkedItem)
return result;
def getParamOptions(self, options):
tuples = list(map(lambda items: self.__tupleToScalaTuple2(items), options))
return gateway.jvm.scala.collection.JavaConversions.collectionAsScalaIterable(tuples)
def getDefaultChecked(self, defaultChecked):
if defaultChecked is None:
defaultChecked = []
return gateway.jvm.scala.collection.JavaConversions.collectionAsScalaIterable(defaultChecked)
def registerHook(self, event, cmd, replName=None):
if replName is None:
self.z.registerHook(event, cmd)

View file

@ -64,7 +64,7 @@ public class DepInterpreterTest {
dep.setInterpreterGroup(intpGroup);
context = new InterpreterContext("note", "id", null, "title", "text", new AuthenticationInfo(),
new HashMap<String, Object>(), new GUI(),
new HashMap<String, Object>(), new GUI(), new GUI(),
new AngularObjectRegistry(intpGroup.getId(), null),
null,
new LinkedList<InterpreterContextRunner>(), null);

View file

@ -197,6 +197,7 @@ public class IPySparkInterpreterTest {
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new GUI(),
null,
null,
null,

View file

@ -115,6 +115,7 @@ public class PySparkInterpreterMatplotlibTest {
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new GUI(),
new AngularObjectRegistry(intpGroup.getId(), null),
new LocalResourcePool("id"),
new LinkedList<InterpreterContextRunner>(),

View file

@ -86,6 +86,7 @@ public class PySparkInterpreterTest {
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new GUI(),
new AngularObjectRegistry(intpGroup.getId(), null),
new LocalResourcePool("id"),
new LinkedList<InterpreterContextRunner>(),

View file

@ -109,6 +109,7 @@ public class SparkInterpreterTest {
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new GUI(),
new AngularObjectRegistry(intpGroup.getId(), null),
new LocalResourcePool("id"),
new LinkedList<InterpreterContextRunner>(),
@ -335,6 +336,7 @@ public class SparkInterpreterTest {
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new GUI(),
new AngularObjectRegistry(intpGroup.getId(), null),
new LocalResourcePool("id"),
new LinkedList<InterpreterContextRunner>(),

View file

@ -68,7 +68,7 @@ public class SparkSqlInterpreterTest {
sql.open();
context = new InterpreterContext("note", "id", null, "title", "text", new AuthenticationInfo(),
new HashMap<String, Object>(), new GUI(),
new HashMap<String, Object>(), new GUI(), new GUI(),
new AngularObjectRegistry(intpGroup.getId(), null),
new LocalResourcePool("id"),
new LinkedList<InterpreterContextRunner>(), new InterpreterOutput(null));

View file

@ -35,7 +35,7 @@ trait AbstractAngularElemTest
override def beforeEach() {
val intpGroup = new InterpreterGroup()
val context = new InterpreterContext("note", "paragraph", null, "title", "text",
new AuthenticationInfo(), new util.HashMap[String, Object](), new GUI(),
new AuthenticationInfo(), new util.HashMap[String, Object](), new GUI(), new GUI(),
new AngularObjectRegistry(intpGroup.getId(), null),
null,
new util.LinkedList[InterpreterContextRunner](),

View file

@ -30,7 +30,7 @@ with BeforeAndAfter with BeforeAndAfterEach with Eventually with Matchers {
override def beforeEach() {
val intpGroup = new InterpreterGroup()
val context = new InterpreterContext("note", "id", null, "title", "text", new AuthenticationInfo(),
new java.util.HashMap[String, Object](), new GUI(), new AngularObjectRegistry(
new java.util.HashMap[String, Object](), new GUI(), new GUI(), new AngularObjectRegistry(
intpGroup.getId(), null),
null,
new java.util.LinkedList[InterpreterContextRunner](),

View file

@ -149,6 +149,8 @@ public class Input<T> implements Serializable {
// checkbox form with " or " as delimiter: will be
// expanded to "US or JP"
private static final Pattern VAR_PTN = Pattern.compile("([_])?[$][{]([^=}]*([=][^}]*)?)[}]");
private static final Pattern VAR_NOTE_PTN =
Pattern.compile("([_])?[$]{2}[{]([^=}]*([=][^}]*)?)[}]");
private static String[] getNameAndDisplayName(String str) {
Pattern p = Pattern.compile("([^(]*)\\s*[(]([^)]*)[)]");
@ -275,15 +277,21 @@ public class Input<T> implements Serializable {
return input;
}
public static LinkedHashMap<String, Input> extractSimpleQueryForm(String script) {
public static LinkedHashMap<String, Input> extractSimpleQueryForm(String script,
boolean noteForm) {
LinkedHashMap<String, Input> forms = new LinkedHashMap<>();
if (script == null) {
return forms;
}
String replaced = script;
Matcher match = VAR_PTN.matcher(replaced);
Pattern pattern = noteForm ? VAR_NOTE_PTN : VAR_PTN;
Matcher match = pattern.matcher(replaced);
while (match.find()) {
int first = match.start();
if (!noteForm && first > 0 && replaced.charAt(first - 1) == '$') {
continue;
}
Input form = getInputForm(match);
forms.put(form.name, form);
}
@ -294,11 +302,18 @@ public class Input<T> implements Serializable {
private static final String DEFAULT_DELIMITER = ",";
public static String getSimpleQuery(Map<String, Object> params, String script) {
public static String getSimpleQuery(Map<String, Object> params, String script, boolean noteForm) {
String replaced = script;
Matcher match = VAR_PTN.matcher(replaced);
Pattern pattern = noteForm ? VAR_NOTE_PTN : VAR_PTN;
Matcher match = pattern.matcher(replaced);
while (match.find()) {
int first = match.start();
if (!noteForm && first > 0 && replaced.charAt(first - 1) == '$') {
continue;
}
Input input = getInputForm(match);
Object value;
if (params.containsKey(input.name)) {
@ -331,7 +346,7 @@ public class Input<T> implements Serializable {
expanded = value.toString();
}
replaced = match.replaceFirst(expanded);
match = VAR_PTN.matcher(replaced);
match = pattern.matcher(replaced);
}
return replaced;

View file

@ -45,6 +45,7 @@ public abstract class BaseZeppelinContext {
protected int maxResult;
protected InterpreterHookRegistry hooks;
protected GUI gui;
protected GUI noteGui;
private static RemoteEventClientWrapper eventClient;
@ -86,37 +87,99 @@ public abstract class BaseZeppelinContext {
@Deprecated
@ZeppelinApi
public Object input(String name, Object defaultValue) {
return textbox(name, defaultValue.toString());
return textbox(name, defaultValue.toString(), false);
}
@ZeppelinApi
public Object textbox(String name) {
return textbox(name, "");
return textbox(name, "", false);
}
@ZeppelinApi
public Object textbox(String name, String defaultValue) {
return gui.textbox(name, defaultValue);
}
public Object select(String name, Object defaultValue, ParamOption[] paramOptions) {
return gui.select(name, defaultValue, paramOptions);
return textbox(name, defaultValue, false);
}
@ZeppelinApi
public Collection<Object> checkbox(String name, ParamOption[] options) {
return checkbox(name, options, false);
}
@ZeppelinApi
public Collection<Object> checkbox(String name, List<Object> defaultChecked,
ParamOption[] options) {
return checkbox(name, defaultChecked, options, false);
}
@ZeppelinApi
public Object select(String name, Object defaultValue, ParamOption[] paramOptions) {
return select(name, defaultValue, paramOptions, false);
}
@ZeppelinApi
public Object noteTextbox(String name) {
return textbox(name, "");
}
@ZeppelinApi
public Object noteTextbox(String name, String defaultValue) {
return textbox(name, defaultValue, true);
}
@ZeppelinApi
public Collection<Object> noteCheckbox(String name, ParamOption[] options) {
return checkbox(name, options, true);
}
@ZeppelinApi
public Collection<Object> noteCheckbox(String name, List<Object> defaultChecked,
ParamOption[] options) {
return checkbox(name, defaultChecked, options, true);
}
@ZeppelinApi
public Object noteSelect(String name, Object defaultValue, ParamOption[] paramOptions) {
return select(name, defaultValue, paramOptions, true);
}
private Object select(String name, Object defaultValue, ParamOption[] paramOptions,
boolean noteForm) {
if (noteForm) {
return noteGui.select(name, defaultValue, paramOptions);
} else {
return gui.select(name, defaultValue, paramOptions);
}
}
private Object textbox(String name, String defaultValue, boolean noteForm) {
if (noteForm) {
return noteGui.textbox(name, defaultValue);
} else {
return gui.textbox(name, defaultValue);
}
}
private Collection<Object> checkbox(String name, ParamOption[] options,
boolean noteForm) {
List<Object> defaultValues = new LinkedList<>();
for (ParamOption option : options) {
defaultValues.add(option.getValue());
}
return checkbox(name, defaultValues, options);
if (noteForm) {
return noteGui.checkbox(name, defaultValues, options);
} else {
return gui.checkbox(name, defaultValues, options);
}
}
@ZeppelinApi
public Collection<Object> checkbox(String name,
List<Object> defaultValues,
ParamOption[] options) {
return gui.checkbox(name, defaultValues, options);
private Collection<Object> checkbox(String name, List<Object> defaultChecked,
ParamOption[] options, boolean noteForm) {
if (noteForm) {
return noteGui.checkbox(name, defaultChecked, options);
} else {
return gui.checkbox(name, defaultChecked, options);
}
}
public void setGui(GUI o) {
@ -127,6 +190,15 @@ public abstract class BaseZeppelinContext {
return gui;
}
public GUI getNoteGui() {
return noteGui;
}
public void setNoteGui(GUI noteGui) {
this.noteGui = noteGui;
}
private void restartInterpreter() {
}

View file

@ -58,6 +58,7 @@ public class InterpreterContext {
private AuthenticationInfo authenticationInfo;
private Map<String, Object> config = new HashMap<>();
private GUI gui = new GUI();
private GUI noteGui = new GUI();
private AngularObjectRegistry angularObjectRegistry;
private ResourcePool resourcePool;
private List<InterpreterContextRunner> runners = new ArrayList<>();
@ -100,13 +101,14 @@ public class InterpreterContext {
AuthenticationInfo authenticationInfo,
Map<String, Object> config,
GUI gui,
GUI noteGui,
AngularObjectRegistry angularObjectRegistry,
ResourcePool resourcePool,
List<InterpreterContextRunner> runners,
InterpreterOutput out
) {
this(noteId, paragraphId, replName, paragraphTitle, paragraphText, authenticationInfo,
config, gui, angularObjectRegistry, resourcePool, runners, out, null, null);
config, gui, noteGui, angularObjectRegistry, resourcePool, runners, out, null, null);
}
public InterpreterContext(String noteId,
@ -117,6 +119,7 @@ public class InterpreterContext {
AuthenticationInfo authenticationInfo,
Map<String, Object> config,
GUI gui,
GUI noteGui,
AngularObjectRegistry angularObjectRegistry,
ResourcePool resourcePool,
List<InterpreterContextRunner> runners,
@ -132,6 +135,7 @@ public class InterpreterContext {
this.authenticationInfo = authenticationInfo;
this.config = config;
this.gui = gui;
this.noteGui = noteGui;
this.angularObjectRegistry = angularObjectRegistry;
this.resourcePool = resourcePool;
this.runners = runners;
@ -148,6 +152,7 @@ public class InterpreterContext {
AuthenticationInfo authenticationInfo,
Map<String, Object> config,
GUI gui,
GUI noteGui,
AngularObjectRegistry angularObjectRegistry,
ResourcePool resourcePool,
List<InterpreterContextRunner> contextRunners,
@ -156,7 +161,7 @@ public class InterpreterContext {
RemoteInterpreterEventClient eventClient,
Map<String, Integer> progressMap) {
this(noteId, paragraphId, replName, paragraphTitle, paragraphText, authenticationInfo,
config, gui, angularObjectRegistry, resourcePool, contextRunners, output,
config, gui, noteGui, angularObjectRegistry, resourcePool, contextRunners, output,
remoteWorksController, progressMap);
this.client = new RemoteEventClient(eventClient);
}
@ -193,6 +198,10 @@ public class InterpreterContext {
return gui;
}
public GUI getNoteGui() {
return noteGui;
}
public AngularObjectRegistry getAngularObjectRegistry() {
return angularObjectRegistry;
}

View file

@ -456,7 +456,8 @@ public class RemoteInterpreterServer
}
return convert(result,
context.getConfig(),
context.getGui());
context.getGui(),
context.getNoteGui());
}
@Override
@ -743,6 +744,7 @@ public class RemoteInterpreterServer
(Map<String, Object>) gson.fromJson(ric.getConfig(),
new TypeToken<Map<String, Object>>() {}.getType()),
GUI.fromJson(ric.getGui()),
GUI.fromJson(ric.getNoteGui()),
interpreterGroup.getAngularObjectRegistry(),
interpreterGroup.getResourcePool(),
contextRunners, output, remoteWorksController, eventClient, progressMap);
@ -874,7 +876,7 @@ public class RemoteInterpreterServer
}
private RemoteInterpreterResult convert(InterpreterResult result,
Map<String, Object> config, GUI gui) {
Map<String, Object> config, GUI gui, GUI noteGui) {
List<RemoteInterpreterResultMessage> msg = new LinkedList<>();
for (InterpreterResultMessage m : result.message()) {
@ -887,7 +889,8 @@ public class RemoteInterpreterServer
result.code().name(),
msg,
gson.toJson(config),
gui.toJson());
gui.toJson(),
noteGui.toJson());
}
@Override

View file

@ -51,7 +51,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-6-17")
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-10-22")
public class CallbackInfo implements org.apache.thrift.TBase<CallbackInfo, CallbackInfo._Fields>, java.io.Serializable, Cloneable, Comparable<CallbackInfo> {
private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("CallbackInfo");

View file

@ -51,7 +51,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-3-27")
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-10-22")
public class InterpreterCompletion implements org.apache.thrift.TBase<InterpreterCompletion, InterpreterCompletion._Fields>, java.io.Serializable, Cloneable, Comparable<InterpreterCompletion> {
private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("InterpreterCompletion");

View file

@ -51,7 +51,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-3-27")
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-10-22")
public class RemoteApplicationResult implements org.apache.thrift.TBase<RemoteApplicationResult, RemoteApplicationResult._Fields>, java.io.Serializable, Cloneable, Comparable<RemoteApplicationResult> {
private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("RemoteApplicationResult");

View file

@ -51,7 +51,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-6-17")
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-10-22")
public class RemoteInterpreterCallbackService {
public interface Iface {

View file

@ -51,7 +51,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-3-27")
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-10-22")
public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteInterpreterContext, RemoteInterpreterContext._Fields>, java.io.Serializable, Cloneable, Comparable<RemoteInterpreterContext> {
private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("RemoteInterpreterContext");
@ -63,7 +63,8 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
private static final org.apache.thrift.protocol.TField AUTHENTICATION_INFO_FIELD_DESC = new org.apache.thrift.protocol.TField("authenticationInfo", org.apache.thrift.protocol.TType.STRING, (short)6);
private static final org.apache.thrift.protocol.TField CONFIG_FIELD_DESC = new org.apache.thrift.protocol.TField("config", org.apache.thrift.protocol.TType.STRING, (short)7);
private static final org.apache.thrift.protocol.TField GUI_FIELD_DESC = new org.apache.thrift.protocol.TField("gui", org.apache.thrift.protocol.TType.STRING, (short)8);
private static final org.apache.thrift.protocol.TField RUNNERS_FIELD_DESC = new org.apache.thrift.protocol.TField("runners", org.apache.thrift.protocol.TType.STRING, (short)9);
private static final org.apache.thrift.protocol.TField NOTE_GUI_FIELD_DESC = new org.apache.thrift.protocol.TField("noteGui", org.apache.thrift.protocol.TType.STRING, (short)9);
private static final org.apache.thrift.protocol.TField RUNNERS_FIELD_DESC = new org.apache.thrift.protocol.TField("runners", org.apache.thrift.protocol.TType.STRING, (short)10);
private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
static {
@ -79,6 +80,7 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
public String authenticationInfo; // required
public String config; // required
public String gui; // required
public String noteGui; // required
public String runners; // required
/** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
@ -91,7 +93,8 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
AUTHENTICATION_INFO((short)6, "authenticationInfo"),
CONFIG((short)7, "config"),
GUI((short)8, "gui"),
RUNNERS((short)9, "runners");
NOTE_GUI((short)9, "noteGui"),
RUNNERS((short)10, "runners");
private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
@ -122,7 +125,9 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
return CONFIG;
case 8: // GUI
return GUI;
case 9: // RUNNERS
case 9: // NOTE_GUI
return NOTE_GUI;
case 10: // RUNNERS
return RUNNERS;
default:
return null;
@ -183,6 +188,8 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
tmpMap.put(_Fields.GUI, new org.apache.thrift.meta_data.FieldMetaData("gui", org.apache.thrift.TFieldRequirementType.DEFAULT,
new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
tmpMap.put(_Fields.NOTE_GUI, new org.apache.thrift.meta_data.FieldMetaData("noteGui", org.apache.thrift.TFieldRequirementType.DEFAULT,
new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
tmpMap.put(_Fields.RUNNERS, new org.apache.thrift.meta_data.FieldMetaData("runners", org.apache.thrift.TFieldRequirementType.DEFAULT,
new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
metaDataMap = Collections.unmodifiableMap(tmpMap);
@ -201,6 +208,7 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
String authenticationInfo,
String config,
String gui,
String noteGui,
String runners)
{
this();
@ -212,6 +220,7 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
this.authenticationInfo = authenticationInfo;
this.config = config;
this.gui = gui;
this.noteGui = noteGui;
this.runners = runners;
}
@ -243,6 +252,9 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
if (other.isSetGui()) {
this.gui = other.gui;
}
if (other.isSetNoteGui()) {
this.noteGui = other.noteGui;
}
if (other.isSetRunners()) {
this.runners = other.runners;
}
@ -262,6 +274,7 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
this.authenticationInfo = null;
this.config = null;
this.gui = null;
this.noteGui = null;
this.runners = null;
}
@ -457,6 +470,30 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
}
}
public String getNoteGui() {
return this.noteGui;
}
public RemoteInterpreterContext setNoteGui(String noteGui) {
this.noteGui = noteGui;
return this;
}
public void unsetNoteGui() {
this.noteGui = null;
}
/** Returns true if field noteGui is set (has been assigned a value) and false otherwise */
public boolean isSetNoteGui() {
return this.noteGui != null;
}
public void setNoteGuiIsSet(boolean value) {
if (!value) {
this.noteGui = null;
}
}
public String getRunners() {
return this.runners;
}
@ -547,6 +584,14 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
}
break;
case NOTE_GUI:
if (value == null) {
unsetNoteGui();
} else {
setNoteGui((String)value);
}
break;
case RUNNERS:
if (value == null) {
unsetRunners();
@ -584,6 +629,9 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
case GUI:
return getGui();
case NOTE_GUI:
return getNoteGui();
case RUNNERS:
return getRunners();
@ -614,6 +662,8 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
return isSetConfig();
case GUI:
return isSetGui();
case NOTE_GUI:
return isSetNoteGui();
case RUNNERS:
return isSetRunners();
}
@ -705,6 +755,15 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
return false;
}
boolean this_present_noteGui = true && this.isSetNoteGui();
boolean that_present_noteGui = true && that.isSetNoteGui();
if (this_present_noteGui || that_present_noteGui) {
if (!(this_present_noteGui && that_present_noteGui))
return false;
if (!this.noteGui.equals(that.noteGui))
return false;
}
boolean this_present_runners = true && this.isSetRunners();
boolean that_present_runners = true && that.isSetRunners();
if (this_present_runners || that_present_runners) {
@ -761,6 +820,11 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
if (present_gui)
list.add(gui);
boolean present_noteGui = true && (isSetNoteGui());
list.add(present_noteGui);
if (present_noteGui)
list.add(noteGui);
boolean present_runners = true && (isSetRunners());
list.add(present_runners);
if (present_runners)
@ -857,6 +921,16 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
return lastComparison;
}
}
lastComparison = Boolean.valueOf(isSetNoteGui()).compareTo(other.isSetNoteGui());
if (lastComparison != 0) {
return lastComparison;
}
if (isSetNoteGui()) {
lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.noteGui, other.noteGui);
if (lastComparison != 0) {
return lastComparison;
}
}
lastComparison = Boolean.valueOf(isSetRunners()).compareTo(other.isSetRunners());
if (lastComparison != 0) {
return lastComparison;
@ -951,6 +1025,14 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
}
first = false;
if (!first) sb.append(", ");
sb.append("noteGui:");
if (this.noteGui == null) {
sb.append("null");
} else {
sb.append(this.noteGui);
}
first = false;
if (!first) sb.append(", ");
sb.append("runners:");
if (this.runners == null) {
sb.append("null");
@ -1065,7 +1147,15 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
}
break;
case 9: // RUNNERS
case 9: // NOTE_GUI
if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
struct.noteGui = iprot.readString();
struct.setNoteGuiIsSet(true);
} else {
org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
}
break;
case 10: // RUNNERS
if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
struct.runners = iprot.readString();
struct.setRunnersIsSet(true);
@ -1128,6 +1218,11 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
oprot.writeString(struct.gui);
oprot.writeFieldEnd();
}
if (struct.noteGui != null) {
oprot.writeFieldBegin(NOTE_GUI_FIELD_DESC);
oprot.writeString(struct.noteGui);
oprot.writeFieldEnd();
}
if (struct.runners != null) {
oprot.writeFieldBegin(RUNNERS_FIELD_DESC);
oprot.writeString(struct.runners);
@ -1175,10 +1270,13 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
if (struct.isSetGui()) {
optionals.set(7);
}
if (struct.isSetRunners()) {
if (struct.isSetNoteGui()) {
optionals.set(8);
}
oprot.writeBitSet(optionals, 9);
if (struct.isSetRunners()) {
optionals.set(9);
}
oprot.writeBitSet(optionals, 10);
if (struct.isSetNoteId()) {
oprot.writeString(struct.noteId);
}
@ -1203,6 +1301,9 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
if (struct.isSetGui()) {
oprot.writeString(struct.gui);
}
if (struct.isSetNoteGui()) {
oprot.writeString(struct.noteGui);
}
if (struct.isSetRunners()) {
oprot.writeString(struct.runners);
}
@ -1211,7 +1312,7 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
@Override
public void read(org.apache.thrift.protocol.TProtocol prot, RemoteInterpreterContext struct) throws org.apache.thrift.TException {
TTupleProtocol iprot = (TTupleProtocol) prot;
BitSet incoming = iprot.readBitSet(9);
BitSet incoming = iprot.readBitSet(10);
if (incoming.get(0)) {
struct.noteId = iprot.readString();
struct.setNoteIdIsSet(true);
@ -1245,6 +1346,10 @@ public class RemoteInterpreterContext implements org.apache.thrift.TBase<RemoteI
struct.setGuiIsSet(true);
}
if (incoming.get(8)) {
struct.noteGui = iprot.readString();
struct.setNoteGuiIsSet(true);
}
if (incoming.get(9)) {
struct.runners = iprot.readString();
struct.setRunnersIsSet(true);
}

View file

@ -51,7 +51,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-3-27")
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-10-22")
public class RemoteInterpreterEvent implements org.apache.thrift.TBase<RemoteInterpreterEvent, RemoteInterpreterEvent._Fields>, java.io.Serializable, Cloneable, Comparable<RemoteInterpreterEvent> {
private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("RemoteInterpreterEvent");

View file

@ -51,7 +51,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-3-27")
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-10-22")
public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteInterpreterResult, RemoteInterpreterResult._Fields>, java.io.Serializable, Cloneable, Comparable<RemoteInterpreterResult> {
private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("RemoteInterpreterResult");
@ -59,6 +59,7 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
private static final org.apache.thrift.protocol.TField MSG_FIELD_DESC = new org.apache.thrift.protocol.TField("msg", org.apache.thrift.protocol.TType.LIST, (short)2);
private static final org.apache.thrift.protocol.TField CONFIG_FIELD_DESC = new org.apache.thrift.protocol.TField("config", org.apache.thrift.protocol.TType.STRING, (short)3);
private static final org.apache.thrift.protocol.TField GUI_FIELD_DESC = new org.apache.thrift.protocol.TField("gui", org.apache.thrift.protocol.TType.STRING, (short)4);
private static final org.apache.thrift.protocol.TField NOTE_GUI_FIELD_DESC = new org.apache.thrift.protocol.TField("noteGui", org.apache.thrift.protocol.TType.STRING, (short)5);
private static final Map<Class<? extends IScheme>, SchemeFactory> schemes = new HashMap<Class<? extends IScheme>, SchemeFactory>();
static {
@ -70,13 +71,15 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
public List<RemoteInterpreterResultMessage> msg; // required
public String config; // required
public String gui; // required
public String noteGui; // required
/** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
public enum _Fields implements org.apache.thrift.TFieldIdEnum {
CODE((short)1, "code"),
MSG((short)2, "msg"),
CONFIG((short)3, "config"),
GUI((short)4, "gui");
GUI((short)4, "gui"),
NOTE_GUI((short)5, "noteGui");
private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
@ -99,6 +102,8 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
return CONFIG;
case 4: // GUI
return GUI;
case 5: // NOTE_GUI
return NOTE_GUI;
default:
return null;
}
@ -151,6 +156,8 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
tmpMap.put(_Fields.GUI, new org.apache.thrift.meta_data.FieldMetaData("gui", org.apache.thrift.TFieldRequirementType.DEFAULT,
new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
tmpMap.put(_Fields.NOTE_GUI, new org.apache.thrift.meta_data.FieldMetaData("noteGui", org.apache.thrift.TFieldRequirementType.DEFAULT,
new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING)));
metaDataMap = Collections.unmodifiableMap(tmpMap);
org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(RemoteInterpreterResult.class, metaDataMap);
}
@ -162,13 +169,15 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
String code,
List<RemoteInterpreterResultMessage> msg,
String config,
String gui)
String gui,
String noteGui)
{
this();
this.code = code;
this.msg = msg;
this.config = config;
this.gui = gui;
this.noteGui = noteGui;
}
/**
@ -191,6 +200,9 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
if (other.isSetGui()) {
this.gui = other.gui;
}
if (other.isSetNoteGui()) {
this.noteGui = other.noteGui;
}
}
public RemoteInterpreterResult deepCopy() {
@ -203,6 +215,7 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
this.msg = null;
this.config = null;
this.gui = null;
this.noteGui = null;
}
public String getCode() {
@ -316,6 +329,30 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
}
}
public String getNoteGui() {
return this.noteGui;
}
public RemoteInterpreterResult setNoteGui(String noteGui) {
this.noteGui = noteGui;
return this;
}
public void unsetNoteGui() {
this.noteGui = null;
}
/** Returns true if field noteGui is set (has been assigned a value) and false otherwise */
public boolean isSetNoteGui() {
return this.noteGui != null;
}
public void setNoteGuiIsSet(boolean value) {
if (!value) {
this.noteGui = null;
}
}
public void setFieldValue(_Fields field, Object value) {
switch (field) {
case CODE:
@ -350,6 +387,14 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
}
break;
case NOTE_GUI:
if (value == null) {
unsetNoteGui();
} else {
setNoteGui((String)value);
}
break;
}
}
@ -367,6 +412,9 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
case GUI:
return getGui();
case NOTE_GUI:
return getNoteGui();
}
throw new IllegalStateException();
}
@ -386,6 +434,8 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
return isSetConfig();
case GUI:
return isSetGui();
case NOTE_GUI:
return isSetNoteGui();
}
throw new IllegalStateException();
}
@ -439,6 +489,15 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
return false;
}
boolean this_present_noteGui = true && this.isSetNoteGui();
boolean that_present_noteGui = true && that.isSetNoteGui();
if (this_present_noteGui || that_present_noteGui) {
if (!(this_present_noteGui && that_present_noteGui))
return false;
if (!this.noteGui.equals(that.noteGui))
return false;
}
return true;
}
@ -466,6 +525,11 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
if (present_gui)
list.add(gui);
boolean present_noteGui = true && (isSetNoteGui());
list.add(present_noteGui);
if (present_noteGui)
list.add(noteGui);
return list.hashCode();
}
@ -517,6 +581,16 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
return lastComparison;
}
}
lastComparison = Boolean.valueOf(isSetNoteGui()).compareTo(other.isSetNoteGui());
if (lastComparison != 0) {
return lastComparison;
}
if (isSetNoteGui()) {
lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.noteGui, other.noteGui);
if (lastComparison != 0) {
return lastComparison;
}
}
return 0;
}
@ -568,6 +642,14 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
sb.append(this.gui);
}
first = false;
if (!first) sb.append(", ");
sb.append("noteGui:");
if (this.noteGui == null) {
sb.append("null");
} else {
sb.append(this.noteGui);
}
first = false;
sb.append(")");
return sb.toString();
}
@ -654,6 +736,14 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
}
break;
case 5: // NOTE_GUI
if (schemeField.type == org.apache.thrift.protocol.TType.STRING) {
struct.noteGui = iprot.readString();
struct.setNoteGuiIsSet(true);
} else {
org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
}
break;
default:
org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type);
}
@ -696,6 +786,11 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
oprot.writeString(struct.gui);
oprot.writeFieldEnd();
}
if (struct.noteGui != null) {
oprot.writeFieldBegin(NOTE_GUI_FIELD_DESC);
oprot.writeString(struct.noteGui);
oprot.writeFieldEnd();
}
oprot.writeFieldStop();
oprot.writeStructEnd();
}
@ -726,7 +821,10 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
if (struct.isSetGui()) {
optionals.set(3);
}
oprot.writeBitSet(optionals, 4);
if (struct.isSetNoteGui()) {
optionals.set(4);
}
oprot.writeBitSet(optionals, 5);
if (struct.isSetCode()) {
oprot.writeString(struct.code);
}
@ -745,12 +843,15 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
if (struct.isSetGui()) {
oprot.writeString(struct.gui);
}
if (struct.isSetNoteGui()) {
oprot.writeString(struct.noteGui);
}
}
@Override
public void read(org.apache.thrift.protocol.TProtocol prot, RemoteInterpreterResult struct) throws org.apache.thrift.TException {
TTupleProtocol iprot = (TTupleProtocol) prot;
BitSet incoming = iprot.readBitSet(4);
BitSet incoming = iprot.readBitSet(5);
if (incoming.get(0)) {
struct.code = iprot.readString();
struct.setCodeIsSet(true);
@ -777,6 +878,10 @@ public class RemoteInterpreterResult implements org.apache.thrift.TBase<RemoteIn
struct.gui = iprot.readString();
struct.setGuiIsSet(true);
}
if (incoming.get(4)) {
struct.noteGui = iprot.readString();
struct.setNoteGuiIsSet(true);
}
}
}

View file

@ -51,7 +51,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-3-27")
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-10-22")
public class RemoteInterpreterResultMessage implements org.apache.thrift.TBase<RemoteInterpreterResultMessage, RemoteInterpreterResultMessage._Fields>, java.io.Serializable, Cloneable, Comparable<RemoteInterpreterResultMessage> {
private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("RemoteInterpreterResultMessage");

View file

@ -51,7 +51,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-3-27")
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-10-22")
public class RemoteInterpreterService {
public interface Iface {

View file

@ -51,7 +51,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"})
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-3-27")
@Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2017-10-22")
public class ZeppelinServerResourceParagraphRunner implements org.apache.thrift.TBase<ZeppelinServerResourceParagraphRunner, ZeppelinServerResourceParagraphRunner._Fields>, java.io.Serializable, Cloneable, Comparable<ZeppelinServerResourceParagraphRunner> {
private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("ZeppelinServerResourceParagraphRunner");

View file

@ -27,7 +27,8 @@ struct RemoteInterpreterContext {
6: string authenticationInfo,
7: string config, // json serialized config
8: string gui, // json serialized gui
9: string runners // json serialized runner
9: string noteGui, // json serialized note gui
10: string runners // json serialized runner
}
struct RemoteInterpreterResultMessage {
@ -39,6 +40,7 @@ struct RemoteInterpreterResult {
2: list<RemoteInterpreterResultMessage> msg,
3: string config, // json serialized config
4: string gui // json serialized gui
5: string noteGui // json serialized note gui
}
enum RemoteInterpreterEventType {

View file

@ -47,7 +47,7 @@ public class InputTest {
public void testFormExtraction() {
// textbox form
String script = "${input_form=}";
Map<String, Input> forms = Input.extractSimpleQueryForm(script);
Map<String, Input> forms = Input.extractSimpleQueryForm(script, false);
assertEquals(1, forms.size());
Input form = forms.get("input_form");
assertEquals("input_form", form.name);
@ -57,14 +57,14 @@ public class InputTest {
// textbox form with display name & default value
script = "${input_form(Input Form)=xxx}";
forms = Input.extractSimpleQueryForm(script);
forms = Input.extractSimpleQueryForm(script, false);
form = forms.get("input_form");
assertEquals("xxx", form.defaultValue);
assertTrue(form instanceof TextBox);
// selection form
script = "${select_form(Selection Form)=op1,op1|op2(Option 2)|op3}";
form = Input.extractSimpleQueryForm(script).get("select_form");
form = Input.extractSimpleQueryForm(script, false).get("select_form");
assertEquals("select_form", form.name);
assertEquals("op1", form.defaultValue);
assertTrue(form instanceof Select);
@ -74,7 +74,7 @@ public class InputTest {
// checkbox form
script = "${checkbox:checkbox_form=op1,op1|op2|op3}";
form = Input.extractSimpleQueryForm(script).get("checkbox_form");
form = Input.extractSimpleQueryForm(script, false).get("checkbox_form");
assertEquals("checkbox_form", form.name);
assertTrue(form instanceof CheckBox);
@ -85,7 +85,7 @@ public class InputTest {
// checkbox form with multiple default checks
script = "${checkbox:checkbox_form(Checkbox Form)=op1|op3,op1(Option 1)|op2|op3}";
form = Input.extractSimpleQueryForm(script).get("checkbox_form");
form = Input.extractSimpleQueryForm(script, false).get("checkbox_form");
assertEquals("checkbox_form", form.name);
assertEquals("Checkbox Form", form.displayName);
assertTrue(form instanceof CheckBox);
@ -96,7 +96,7 @@ public class InputTest {
// checkbox form with no default check
script = "${checkbox:checkbox_form(Checkbox Form)=,op1(Option 1)|op2(Option 2)|op3(Option 3)}";
form = Input.extractSimpleQueryForm(script).get("checkbox_form");
form = Input.extractSimpleQueryForm(script, false).get("checkbox_form");
assertEquals("checkbox_form", form.name);
assertEquals("Checkbox Form", form.displayName);
assertTrue(form instanceof CheckBox);
@ -116,14 +116,14 @@ public class InputTest {
params.put("input_form", "some_input");
params.put("select_form", "s_op2");
params.put("checkbox_form", new String[]{"c_op1", "c_op3"});
String replaced = Input.getSimpleQuery(params, script);
String replaced = Input.getSimpleQuery(params, script, false);
assertEquals("INPUT=some_inputSELECTED=s_op2\nCHECKED=c_op1,c_op3", replaced);
// test form substitution with new forms
script = "INPUT=${input_form=}SELECTED=${select_form(Selection Form)=,s_op1|s_op2|s_op3}\n" +
"CHECKED=${checkbox:checkbox_form=c_op1|c_op2,c_op1|c_op2|c_op3}\n" +
"NEW_CHECKED=${checkbox( and ):new_check=nc_a|nc_c,nc_a|nc_b|nc_c}";
replaced = Input.getSimpleQuery(params, script);
replaced = Input.getSimpleQuery(params, script, false);
assertEquals("INPUT=some_inputSELECTED=s_op2\nCHECKED=c_op1,c_op3\n" +
"NEW_CHECKED=nc_a and nc_c", replaced);
@ -131,7 +131,7 @@ public class InputTest {
script = "INPUT=${input_form=}SELECTED=${select_form(Selection Form)=,s_op1|s_op2|s_op3}\n" +
"CHECKED=${checkbox:checkbox_form=c_op1|c_op2,c_op1|c_op2|c_op3_new}\n" +
"NEW_CHECKED=${checkbox( and ):new_check=nc_a|nc_c,nc_a|nc_b|nc_c}";
replaced = Input.getSimpleQuery(params, script);
replaced = Input.getSimpleQuery(params, script, false);
assertEquals("INPUT=some_inputSELECTED=s_op2\nCHECKED=c_op1\n" +
"NEW_CHECKED=nc_a and nc_c", replaced);
}

View file

@ -27,7 +27,7 @@ public class InterpreterContextTest {
public void testThreadLocal() {
assertNull(InterpreterContext.get());
InterpreterContext.set(new InterpreterContext(null, null, null, null, null, null, null, null, null, null, null, null));
InterpreterContext.set(new InterpreterContext(null, null, null, null, null, null, null, null, null, null, null, null, null));
assertNotNull(InterpreterContext.get());
InterpreterContext.remove();

View file

@ -70,6 +70,7 @@ public class InterpreterTest {
null,
null,
null,
null,
null));
Properties p = new Properties();
p.put("p1", "replName #{noteId}, #{paragraphTitle}, #{paragraphId}, #{paragraphText}, #{replName}, #{noteId}, #{user}," +

View file

@ -36,7 +36,7 @@ public class LazyOpenInterpreterTest {
assertFalse("Interpreter is not open", lazyOpenInterpreter.isOpen());
InterpreterContext interpreterContext =
new InterpreterContext("note", "id", null, "title", "text", null, null, null, null, null, null, null);
new InterpreterContext("note", "id", null, "title", "text", null, null, null, null, null, null, null, null);
lazyOpenInterpreter.interpret("intp 1", interpreterContext);
assertTrue("Interpeter is open", lazyOpenInterpreter.isOpen());
}

View file

@ -35,10 +35,7 @@ import org.apache.commons.lang.StringUtils;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.zeppelin.conf.ZeppelinConfiguration;
import org.apache.zeppelin.conf.ZeppelinConfiguration.ConfVars;
import org.apache.zeppelin.display.AngularObject;
import org.apache.zeppelin.display.AngularObjectRegistry;
import org.apache.zeppelin.display.AngularObjectRegistryListener;
import org.apache.zeppelin.display.Input;
import org.apache.zeppelin.display.*;
import org.apache.zeppelin.helium.ApplicationEventListener;
import org.apache.zeppelin.helium.HeliumPackage;
import org.apache.zeppelin.interpreter.*;
@ -353,6 +350,9 @@ public class NotebookServer extends WebSocketServlet
case WATCHER:
switchConnectionToWatcher(conn, messagereceived);
break;
case NOTE_FORMS:
saveNoteForms(conn, userAndRoles, notebook, messagereceived);
break;
default:
break;
}
@ -646,6 +646,8 @@ public class NotebookServer extends WebSocketServlet
}
public void broadcastParagraph(Note note, Paragraph p) {
broadcastNoteForms(note);
if (note.isPersonalizedMode()) {
broadcastParagraphs(p.getUserParagraphMap(), p);
} else {
@ -1224,7 +1226,6 @@ public class NotebookServer extends WebSocketServlet
p.setText((String) fromMessage.get("paragraph"));
}
note.persist(subject);
if (note.isPersonalizedMode()) {
@ -2500,4 +2501,32 @@ public class NotebookServer extends WebSocketServlet
}
setting.clearNoteIdAndParaMap();
}
public void broadcastNoteForms(Note note) {
GUI formsSettings = new GUI();
formsSettings.setForms(note.getNoteForms());
formsSettings.setParams(note.getNoteParams());
broadcast(note.getId(), new Message(OP.NOTE_FORMS).put("formsData", formsSettings));
}
private void saveNoteForms(NotebookSocket conn, HashSet<String> userAndRoles, Notebook notebook,
Message fromMessage) throws IOException {
String noteId = (String) fromMessage.get("noteId");
Map<String, Object> noteParams = (Map<String, Object>) fromMessage.get("noteParams");
if (!hasParagraphWriterPermission(conn, notebook, noteId,
userAndRoles, fromMessage.principal, "update")) {
return;
}
Note note = notebook.getNote(noteId);
if (note != null) {
note.setNoteParams(noteParams);
AuthenticationInfo subject = new AuthenticationInfo(fromMessage.principal);
note.persist(subject);
broadcastNoteForms(note);
}
}
}

View file

@ -63,6 +63,10 @@ abstract public class AbstractZeppelinIT {
return "(//div[@ng-controller=\"ParagraphCtrl\"])[" + paragraphNo + "]";
}
protected String getNoteFormsXPath() {
return "(//div[@id='noteForms'])";
}
protected boolean waitForParagraph(final int paragraphNo, final String state) {
By locator = By.xpath(getParagraphXPath(paragraphNo)
+ "//div[contains(@class, 'control')]//span[2][contains(.,'" + state + "')]");

View file

@ -725,4 +725,164 @@ public class ParagraphActionsIT extends AbstractZeppelinIT {
handleException("Exception in ParagraphActionsIT while testMultipleDynamicFormsSameType ", e);
}
}
@Test
public void testNoteDynamicFormTextInput() throws Exception {
if (!endToEndTestEnabled()) {
return;
}
try {
createNewNote();
setTextOfParagraph(1, "%spark println(\"Hello \"+z.noteTextbox(\"name\", \"world\")) ");
runParagraph(1);
waitForParagraph(1, "FINISHED");
collector.checkThat("Output text is equal to value specified initially", driver.findElement(By.xpath(getParagraphXPath(1) + "//div[contains(@class, 'text plainTextContent')]")).getText(), CoreMatchers.equalTo("Hello world"));
driver.findElement(By.xpath(getNoteFormsXPath() + "//input")).clear();
driver.findElement(By.xpath(getNoteFormsXPath() + "//input")).sendKeys("Zeppelin");
driver.findElement(By.xpath(getNoteFormsXPath() + "//input")).sendKeys(Keys.RETURN);
collector.checkThat("After new data in text input form, output should not be changed",
driver.findElement(By.xpath(getParagraphXPath(1) + "//div[contains(@class, 'text plainTextContent')]")).getText(),
CoreMatchers.equalTo("Hello world"));
runParagraph(1);
waitForParagraph(1, "FINISHED");
collector.checkThat("Only after running the paragraph, we can see the newly updated output",
driver.findElement(By.xpath(getParagraphXPath(1) + "//div[contains(@class, 'text plainTextContent')]")).getText(),
CoreMatchers.equalTo("Hello Zeppelin"));
setTextOfParagraph(2, "%spark println(\"Hello \"+z.noteTextbox(\"name\", \"world\")) ");
runParagraph(2);
waitForParagraph(2, "FINISHED");
collector.checkThat("Running the another paragraph with same form, we can see value from note form",
driver.findElement(By.xpath(getParagraphXPath(2) + "//div[contains(@class, 'text plainTextContent')]")).getText(),
CoreMatchers.equalTo("Hello Zeppelin"));
deleteTestNotebook(driver);
} catch (Exception e) {
handleException("Exception in ParagraphActionsIT while testNoteDynamicFormTextInput ", e);
}
}
@Test
public void testNoteDynamicFormSelect() throws Exception {
if (!endToEndTestEnabled()) {
return;
}
try {
createNewNote();
setTextOfParagraph(1, "%spark println(\"Howdy \"+z.noteSelect(\"names\", Seq((\"1\",\"Alice\"), " +
"(\"2\",\"Bob\"),(\"3\",\"stranger\"))))");
runParagraph(1);
waitForParagraph(1, "FINISHED");
collector.checkThat("Output text should not display any of the options in select form",
driver.findElement(By.xpath(getParagraphXPath(1) + "//div[contains(@class, 'text plainTextContent')]")).getText(),
CoreMatchers.equalTo("Howdy "));
Select dropDownMenu = new Select(driver.findElement(By.xpath("(" + (getNoteFormsXPath() + "//select)[1]"))));
dropDownMenu.selectByVisibleText("Bob");
collector.checkThat("After selection in drop down menu, output should not be changed",
driver.findElement(By.xpath(getParagraphXPath(1) + "//div[contains(@class, 'text plainTextContent')]")).getText(),
CoreMatchers.equalTo("Howdy "));
runParagraph(1);
waitForParagraph(1, "FINISHED");
collector.checkThat("After run paragraph again, we can see the newly updated output",
driver.findElement(By.xpath(getParagraphXPath(1) + "//div[contains(@class, 'text plainTextContent')]")).getText(),
CoreMatchers.equalTo("Howdy 2"));
setTextOfParagraph(2, "%spark println(\"Howdy \"+z.noteSelect(\"names\", Seq((\"1\",\"Alice\"), " +
"(\"2\",\"Bob\"),(\"3\",\"stranger\"))))");
runParagraph(2);
waitForParagraph(2, "FINISHED");
collector.checkThat("Running the another paragraph with same form, we can see value from note form",
driver.findElement(By.xpath(getParagraphXPath(2) + "//div[contains(@class, 'text plainTextContent')]")).getText(),
CoreMatchers.equalTo("Howdy 2"));
deleteTestNotebook(driver);
} catch (Exception e) {
handleException("Exception in ParagraphActionsIT while testNoteDynamicFormSelect ", e);
}
}
@Test
public void testDynamicNoteFormCheckbox() throws Exception {
if (!endToEndTestEnabled()) {
return;
}
try {
createNewNote();
setTextOfParagraph(1, "%spark val options = Seq((\"han\",\"Han\"), (\"leia\",\"Leia\"), " +
"(\"luke\",\"Luke\")); println(\"Greetings \"+z.noteCheckbox(\"skywalkers\",options).mkString(\" and \"))");
runParagraph(1);
waitForParagraph(1, "FINISHED");
collector.checkThat("Output text should display all of the options included in check boxes",
driver.findElement(By.xpath(getParagraphXPath(1) + "//div[contains(@class, 'text plainTextContent')]")).getText(),
CoreMatchers.containsString("Greetings han and leia and luke"));
WebElement firstCheckbox = driver.findElement(By.xpath("(" + getNoteFormsXPath() + "//input[@type='checkbox'])[1]"));
firstCheckbox.click();
collector.checkThat("After unchecking one of the boxes, output should not be changed",
driver.findElement(By.xpath(getParagraphXPath(1) + "//div[contains(@class, 'text plainTextContent')]")).getText(),
CoreMatchers.containsString("Greetings han and leia and luke"));
runParagraph(1);
waitForParagraph(1, "FINISHED");
collector.checkThat("After run paragraph again, we can see the newly updated output",
driver.findElement(By.xpath(getParagraphXPath(1) + "//div[contains(@class, 'text plainTextContent')]")).getText(),
CoreMatchers.containsString("Greetings leia and luke"));
setTextOfParagraph(2, "%spark val options = Seq((\"han\",\"Han\"), (\"leia\",\"Leia\"), " +
"(\"luke\",\"Luke\")); println(\"Greetings \"+z.noteCheckbox(\"skywalkers\",options).mkString(\" and \"))");
runParagraph(2);
waitForParagraph(2, "FINISHED");
collector.checkThat("Running the another paragraph with same form, we can see value from note form",
driver.findElement(By.xpath(getParagraphXPath(2) + "//div[contains(@class, 'text plainTextContent')]")).getText(),
CoreMatchers.containsString("Greetings leia and luke"));
deleteTestNotebook(driver);
} catch (Exception e) {
handleException("Exception in ParagraphActionsIT while testDynamicNoteFormCheckbox ", e);
}
}
@Test
public void testWithNoteAndParagraphDynamicFormTextInput() throws Exception {
if (!endToEndTestEnabled()) {
return;
}
try {
createNewNote();
setTextOfParagraph(1, "%spark println(z.noteTextbox(\"name\", \"note\") + \" \" + z.textbox(\"name\", \"paragraph\")) ");
runParagraph(1);
waitForParagraph(1, "FINISHED");
collector.checkThat("After run paragraph, we can see computed output from two forms",
driver.findElement(By.xpath(getParagraphXPath(1) + "//div[contains(@class, 'text plainTextContent')]")).getText(),
CoreMatchers.equalTo("note paragraph"));
deleteTestNotebook(driver);
} catch (Exception e) {
handleException("Exception in ParagraphActionsIT while testWithNoteAndParagraphDynamicFormTextInput ", e);
}
}
}

View file

@ -0,0 +1,24 @@
import './note-create.css'
.dynamicForm {
margin-right: 20px;
margin-left: 20px;
}
.dynamicForm.form-horizontal .form-group {
margin-right: 0;
margin-left: 0;
}
.dynamicForm.form-horizontal .form-group label {
padding-left: 0;
}
.dynamicForm.form-horizontal .form-group .checkbox-item {
padding-left: 0;
padding-right: 10px;
}
.dynamicForm.form-horizontal .form-group .checkbox-item input {
margin-right: 2px;
}

View file

@ -0,0 +1,71 @@
<!--
Licensed 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.
-->
<form id="{{id}}_form" role="form"
ng-show="!hide"
class="dynamicForm form-horizontal row">
<div class="form-group col-sm-6 col-md-6 col-lg-4"
ng-repeat="formulaire in forms | toArray"
ng-init="loadForm(formulaire, params)">
<label class="control-label input-sm" ng-class="{'disable': disable}">{{formulaire.name}}</label>
<div>
<input class="form-control input-sm"
ng-if="forms[formulaire.name].type == 'TextBox'"
ng-enter="action()"
ng-model="params[formulaire.name]"
ng-class="{'disable': disable}"
name="{{formulaire.name}}" />
</div>
<div ng-if="actiononchange == true">
<select class="form-control input-sm"
ng-if="forms[formulaire.name].type == 'Select'"
ng-change="action()"
ng-model="params[formulaire.name]"
ng-class="{'disable': disable}"
name="{{formulaire.name}}"
ng-options="option.value as (option.displayName||option.value) for option in forms[formulaire.name].options">
</select>
</div>
<div ng-if="actiononchange == false">
<select class="form-control input-sm"
ng-if="forms[formulaire.name].type == 'Select'"
ng-enter="action()"
ng-model="params[formulaire.name]"
ng-class="{'disable': disable}"
name="{{formulaire.name}}"
ng-options="option.value as (option.displayName||option.value) for option in forms[formulaire.name].options">
</select>
</div>
<div ng-if="actiononchange == true &&
forms[formulaire.name].type == 'CheckBox'">
<label ng-repeat="option in forms[formulaire.name].options"
class="checkbox-item input-sm">
<input type="checkbox"
ng-checked="params[formulaire.name].indexOf(option.value) > -1"
ng-class="{'disable': disable}"
ng-click="toggleCheckbox(formulaire, option, params); action()"/> {{option.displayName||option.value}}
</label>
</div>
<div ng-if="actiononchange == false &&
forms[formulaire.name].type == 'CheckBox'">
<label ng-repeat="option in forms[formulaire.name].options"
class="checkbox-item input-sm">
<input type="checkbox"
ng-checked="params[formulaire.name].indexOf(option.value) > -1"
ng-class="{'disable': disable}"
ng-enter="action()"
ng-click="toggleCheckbox(formulaire, option, params)"/> {{option.displayName||option.value}}
</label>
</div>
</div>
</form>

View file

@ -0,0 +1,61 @@
/*
* Licensed 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.
*/
import './dynamic-forms.css'
angular.module('zeppelinWebApp').directive('dynamicForms', DynamicFormDirective)
function DynamicFormDirective($templateRequest, $compile) {
return {
restrict: 'AE',
scope: {
id: '=id',
hide: '=hide',
disable: '=disable',
actiononchange: '=actiononchange',
forms: '=forms',
params: '=params',
action: '=action'
},
link: function (scope, element, attrs, controller) {
scope.loadForm = this.loadForm
scope.toggleCheckbox = this.toggleCheckbox
$templateRequest('app/notebook/dynamic-forms/dynamic-forms.directive.html').then(function (formsHtml) {
let forms = angular.element(formsHtml)
element.append(forms)
$compile(forms)(scope)
})
},
loadForm: function (formulaire, params) {
let value = formulaire.defaultValue
if (params[formulaire.name]) {
value = params[formulaire.name]
}
params[formulaire.name] = value
},
toggleCheckbox: function (formulaire, option, params) {
let idx = params[formulaire.name].indexOf(option.value)
if (idx > -1) {
params[formulaire.name].splice(idx, 1)
} else {
params[formulaire.name].push(option.value)
}
}
}
}

View file

@ -27,6 +27,9 @@ function NotebookCtrl ($scope, $route, $routeParams, $location, $rootScope,
ngToast.dismiss()
$scope.note = null
$scope.actionOnFormSelectionChange = true
$scope.hideForms = false
$scope.disableForms = false
$scope.editorToggled = false
$scope.tableToggled = false
$scope.viewOnly = false
@ -1331,6 +1334,22 @@ function NotebookCtrl ($scope, $route, $routeParams, $location, $rootScope,
}
}
$scope.$on('noteForms', function (event, data) {
$scope.note.noteForms = data.formsData.forms
$scope.note.noteParams = data.formsData.params
})
$scope.isShowNoteForms = function() {
if ($scope.note && !angular.equals({}, $scope.note.noteForms)) {
return true
}
return false
}
$scope.saveNoteForms = function () {
websocketMsgSrv.saveNoteForms($scope.note)
}
$scope.$on('$destroy', function () {
angular.element(window).off('beforeunload')
$scope.killSaveTimer()

View file

@ -111,6 +111,22 @@ limitations under the License.
</div>
<div class="note-jump"></div>
<div id="noteForms" ng-if="isShowNoteForms()" class="paragraph-space box">
<div>
<h4>Note forms</h4>
</div>
<hr />
<div>
<dynamic-forms
id="note.id"
hide="hideForms"
disable="disableForms"
actiononchange="actionOnFormSelectionChange"
forms="note.noteForms"
params="note.noteParams"
action="saveNoteForms"></dynamic-forms>
</div>
</div>
<!-- Include the paragraphs according to the note, pass the note to init function -->
<div id="{{currentParagraph.id}}_paragraphColumn_main"

View file

@ -1,71 +0,0 @@
<!--
Licensed 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.
-->
<form id="{{paragraph.id}}_form" role="form"
ng-show="!paragraph.config.tableHide"
class=" paragraphForm form-horizontal row">
<div class="form-group col-sm-6 col-md-6 col-lg-4"
ng-repeat="formulaire in paragraph.settings.forms | toArray"
ng-init="loadForm(formulaire, paragraph.settings.params)">
<label class="control-label input-sm" ng-class="{'disable': paragraph.status == 'RUNNING' || paragraph.status == 'PENDING' }">{{formulaire.name}}</label>
<div>
<input class="form-control input-sm"
ng-if="paragraph.settings.forms[formulaire.name].type == 'TextBox'"
ng-enter="runParagraphFromButton(getEditorValue())"
ng-model="paragraph.settings.params[formulaire.name]"
ng-class="{'disable': paragraph.status == 'RUNNING' || paragraph.status == 'PENDING' }"
name="{{formulaire.name}}" />
</div>
<div ng-if="paragraph.config.runOnSelectionChange == true">
<select class="form-control input-sm"
ng-if="paragraph.settings.forms[formulaire.name].type == 'Select'"
ng-change="runParagraphFromButton(getEditorValue())"
ng-model="paragraph.settings.params[formulaire.name]"
ng-class="{'disable': paragraph.status == 'RUNNING' || paragraph.status == 'PENDING' }"
name="{{formulaire.name}}"
ng-options="option.value as (option.displayName||option.value) for option in paragraph.settings.forms[formulaire.name].options">
</select>
</div>
<div ng-if="paragraph.config.runOnSelectionChange == false">
<select class="form-control input-sm"
ng-if="paragraph.settings.forms[formulaire.name].type == 'Select'"
ng-enter="runParagraphFromButton(getEditorValue())"
ng-model="paragraph.settings.params[formulaire.name]"
ng-class="{'disable': paragraph.status == 'RUNNING' || paragraph.status == 'PENDING' }"
name="{{formulaire.name}}"
ng-options="option.value as (option.displayName||option.value) for option in paragraph.settings.forms[formulaire.name].options">
</select>
</div>
<div ng-if="paragraph.config.runOnSelectionChange == true &&
paragraph.settings.forms[formulaire.name].type == 'CheckBox'">
<label ng-repeat="option in paragraph.settings.forms[formulaire.name].options"
class="checkbox-item input-sm">
<input type="checkbox"
ng-class="{'disable': paragraph.status == 'RUNNING' || paragraph.status == 'PENDING' }"
ng-checked="paragraph.settings.params[formulaire.name].indexOf(option.value) > -1"
ng-click="toggleCheckbox(formulaire, option, false); runParagraphFromButton(getEditorValue())"/> {{option.displayName||option.value}}
</label>
</div>
<div ng-if="paragraph.config.runOnSelectionChange == false &&
paragraph.settings.forms[formulaire.name].type == 'CheckBox'">
<label ng-repeat="option in paragraph.settings.forms[formulaire.name].options"
class="checkbox-item input-sm">
<input type="checkbox"
ng-class="{'disable': paragraph.status == 'RUNNING' || paragraph.status == 'PENDING' }"
ng-checked="paragraph.settings.params[formulaire.name].indexOf(option.value) > -1"
ng-enter="runParagraphFromButton(getEditorValue())"
ng-click="toggleCheckbox(formulaire, option, false)"/> {{option.displayName||option.value}}
</label>
</div>
</div>
</form>

View file

@ -466,9 +466,9 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams, $loca
$scope.runParagraph(paragraphText, true, false)
}
$scope.runParagraphFromButton = function (paragraphText) {
$scope.runParagraphFromButton = function () {
// we come here from the view, so we don't need to call `$digest()`
$scope.runParagraph(paragraphText, false, false)
$scope.runParagraph($scope.getEditorValue(), false, false)
}
$scope.turnOnAutoRun = function (paragraph) {
@ -657,24 +657,6 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams, $loca
commitParagraph(paragraph)
}
$scope.loadForm = function (formulaire, params) {
let value = formulaire.defaultValue
if (params[formulaire.name]) {
value = params[formulaire.name]
}
$scope.paragraph.settings.params[formulaire.name] = value
}
$scope.toggleCheckbox = function (formulaire, option) {
let idx = $scope.paragraph.settings.params[formulaire.name].indexOf(option.value)
if (idx > -1) {
$scope.paragraph.settings.params[formulaire.name].splice(idx, 1)
} else {
$scope.paragraph.settings.params[formulaire.name].push(option.value)
}
}
$scope.aceChanged = function (_, editor) {
let session = editor.getSession()
let dirtyText = session.getValue()

View file

@ -34,7 +34,7 @@ describe('Controller: ParagraphCtrl', function () {
let functions = ['isRunning', 'getIframeDimensions', 'cancelParagraph', 'runParagraph', 'saveParagraph',
'moveUp', 'moveDown', 'insertNew', 'removeParagraph', 'toggleEditor', 'closeEditor', 'openEditor',
'closeTable', 'openTable', 'showTitle', 'hideTitle', 'setTitle', 'showLineNumbers', 'hideLineNumbers',
'changeColWidth', 'columnWidthClass', 'toggleOutput', 'loadForm',
'changeColWidth', 'columnWidthClass', 'toggleOutput',
'aceChanged', 'aceLoaded', 'getEditorValue', 'getProgress', 'getExecutionTime', 'isResultOutdated']
functions.forEach(function (fn) {

View file

@ -303,28 +303,6 @@ table.table-shortcut {
margin-left: -3px;
}
/*
Paragraph Forms CSS
*/
.paragraphForm.form-horizontal .form-group {
margin-right: 0;
margin-left: 0;
}
.paragraphForm.form-horizontal .form-group label {
padding-left: 0;
}
.paragraphForm.form-horizontal .form-group .checkbox-item {
padding-left: 0;
padding-right: 10px;
}
.paragraphForm.form-horizontal .form-group .checkbox-item input {
margin-right: 2px;
}
/*
Ace Text Editor CSS
*/

View file

@ -49,7 +49,16 @@ limitations under the License.
</div>
<div ng-include src="'app/notebook/paragraph/paragraph-progress-bar.html'"></div>
<div ng-include src="'app/notebook/paragraph/paragraph-parameterized-query-form.html'"></div>
<div>
<dynamic-forms
id="paragraph.id"
hide="paragraph.config.tableHide"
disable="paragraph.status == 'RUNNING' || paragraph.status == 'PENDING'"
actiononchange="paragraph.config.runOnSelectionChange"
forms="paragraph.settings.forms"
params="paragraph.settings.params"
action="runParagraphFromButton"></dynamic-forms>
</div>
<!-- Rendering -->
<div class="tableDisplay"

View file

@ -140,6 +140,8 @@ function WebsocketEventFactory ($rootScope, $websocket, $location, baseUrlSrv) {
$rootScope.$broadcast('noteRevision', data)
} else if (op === 'INTERPRETER_BINDINGS') {
$rootScope.$broadcast('interpreterBindings', data)
} else if (op === 'NOTE_FORMS') {
$rootScope.$broadcast('noteForms', data)
} else if (op === 'ERROR_INFO') {
BootstrapDialog.show({
closable: false,

View file

@ -340,5 +340,14 @@ function WebsocketMessageService ($rootScope, websocketEvents) {
websocketEvents.sendNewEvent({op: 'GET_INTERPRETER_SETTINGS'})
},
saveNoteForms: function (note) {
websocketEvents.sendNewEvent({op: 'NOTE_FORMS',
data: {
noteId: note.id,
noteParams: note.noteParams
}
})
}
}
}

View file

@ -57,6 +57,7 @@ import './app/search/result-list.controller.js'
import './app/search/search.service.js'
import './app/helium'
import './app/helium/helium.service.js'
import './app/notebook/dynamic-forms/dynamic-forms.directive.js'
import './components/array-ordering/array-ordering.service.js'
import './components/navbar/navbar.controller.js'
import './components/navbar/expand-collapse/expand-collapse.directive.js'

View file

@ -231,11 +231,15 @@ public class RemoteInterpreter extends Interpreter {
context.getConfig().clear();
context.getConfig().putAll(remoteConfig);
GUI currentGUI = context.getGui();
GUI currentNoteGUI = context.getNoteGui();
if (form == FormType.NATIVE) {
GUI remoteGui = GUI.fromJson(remoteResult.getGui());
GUI remoteNoteGui = GUI.fromJson(remoteResult.getNoteGui());
currentGUI.clear();
currentGUI.setParams(remoteGui.getParams());
currentGUI.setForms(remoteGui.getForms());
currentNoteGUI.setParams(remoteNoteGui.getParams());
currentNoteGUI.setForms(remoteNoteGui.getForms());
} else if (form == FormType.SIMPLE) {
final Map<String, Input> currentForms = currentGUI.getForms();
final Map<String, Object> currentParams = currentGUI.getParams();
@ -391,7 +395,8 @@ public class RemoteInterpreter extends Interpreter {
private RemoteInterpreterContext convert(InterpreterContext ic) {
return new RemoteInterpreterContext(ic.getNoteId(), ic.getParagraphId(), ic.getReplName(),
ic.getParagraphTitle(), ic.getParagraphText(), gson.toJson(ic.getAuthenticationInfo()),
gson.toJson(ic.getConfig()), gson.toJson(ic.getGui()), gson.toJson(ic.getRunners()));
gson.toJson(ic.getConfig()), gson.toJson(ic.getGui()), gson.toJson(ic.getNoteGui()),
gson.toJson(ic.getRunners()));
}
private InterpreterResult convert(RemoteInterpreterResult result) {

View file

@ -73,6 +73,9 @@ public class Note implements ParagraphJobListener, JsonSerializable {
private String name = "";
private String id;
private Map<String, Object> noteParams = new HashMap<>();
private LinkedHashMap<String, Input> noteForms = new LinkedHashMap<>();
private transient ZeppelinConfiguration conf = ZeppelinConfiguration.create();
@ -157,6 +160,22 @@ public class Note implements ParagraphJobListener, JsonSerializable {
return name;
}
public Map<String, Object> getNoteParams() {
return noteParams;
}
public void setNoteParams(Map<String, Object> noteParams) {
this.noteParams = noteParams;
}
public LinkedHashMap<String, Input> getNoteForms() {
return noteForms;
}
public void setNoteForms(LinkedHashMap<String, Input> noteForms) {
this.noteForms = noteForms;
}
public String getNameWithoutPath() {
String notePath = getName();

View file

@ -427,15 +427,27 @@ public class Paragraph extends Job implements Cloneable, JsonSerializable {
} else if (repl.getFormType() == FormType.SIMPLE) {
String scriptBody = getScriptBody();
// inputs will be built from script body
LinkedHashMap<String, Input> inputs = Input.extractSimpleQueryForm(scriptBody);
LinkedHashMap<String, Input> inputs = Input.extractSimpleQueryForm(scriptBody, false);
LinkedHashMap<String, Input> noteInputs = Input.extractSimpleQueryForm(scriptBody, true);
final AngularObjectRegistry angularRegistry =
repl.getInterpreterGroup().getAngularObjectRegistry();
scriptBody = extractVariablesFromAngularRegistry(scriptBody, inputs, angularRegistry);
settings.setForms(inputs);
script = Input.getSimpleQuery(settings.getParams(), scriptBody);
if (!noteInputs.isEmpty()) {
if (!note.getNoteForms().isEmpty()) {
Map<String, Input> currentNoteForms = note.getNoteForms();
for (String s : noteInputs.keySet()) {
if (!currentNoteForms.containsKey(s)) {
currentNoteForms.put(s, noteInputs.get(s));
}
}
} else {
note.setNoteForms(noteInputs);
}
}
script = Input.getSimpleQuery(note.getNoteParams(), scriptBody, true);
script = Input.getSimpleQuery(settings.getParams(), script, false);
}
logger.debug("RUN : " + script);
try {
@ -443,6 +455,11 @@ public class Paragraph extends Job implements Cloneable, JsonSerializable {
InterpreterContext.set(context);
InterpreterResult ret = repl.interpret(script, context);
if (repl.getFormType() == FormType.NATIVE) {
note.setNoteParams(context.getNoteGui().getParams());
note.setNoteForms(context.getNoteGui().getForms());
}
if (Code.KEEP_PREVIOUS_RESULT == ret.code()) {
return getReturn();
}
@ -584,8 +601,8 @@ public class Paragraph extends Job implements Cloneable, JsonSerializable {
InterpreterContext interpreterContext =
new InterpreterContext(note.getId(), getId(), getRequiredReplName(), this.getTitle(),
this.getText(), this.getAuthenticationInfo(), this.getConfig(), this.settings, registry,
resourcePool, runners, output);
this.getText(), this.getAuthenticationInfo(), this.getConfig(), this.settings,
getNoteGui(), registry, resourcePool, runners, output);
return interpreterContext;
}
@ -618,13 +635,12 @@ public class Paragraph extends Job implements Cloneable, JsonSerializable {
InterpreterContext interpreterContext =
new InterpreterContext(note.getId(), getId(), getRequiredReplName(), this.getTitle(),
this.getText(), this.getAuthenticationInfo(), this.getConfig(), this.settings, registry,
resourcePool, runners, output);
this.getText(), this.getAuthenticationInfo(), this.getConfig(), this.settings,
getNoteGui(), registry, resourcePool, runners, output);
return interpreterContext;
}
public InterpreterContextRunner getInterpreterContextRunner() {
return new ParagraphRunner(note, note.getId(), getId());
}
@ -800,6 +816,13 @@ public class Paragraph extends Job implements Cloneable, JsonSerializable {
return runtimeInfos;
}
private GUI getNoteGui() {
GUI gui = new GUI();
gui.setParams(this.note.getNoteParams());
gui.setForms(this.note.getNoteForms());
return gui;
}
@Override
public boolean equals(Object o) {
if (this == o) {

View file

@ -178,8 +178,9 @@ public class Message implements JsonSerializable {
NOTE_UPDATED, // [s-c] paragraph updated(name, config)
RUN_ALL_PARAGRAPHS, // [c-s] run all paragraphs
PARAGRAPH_EXECUTED_BY_SPELL, // [c-s] paragraph was executed by spell
RUN_PARAGRAPH_USING_SPELL, // [s-c] run paragraph using spell
PARAS_INFO // [s-c] paragraph runtime infos
RUN_PARAGRAPH_USING_SPELL, // [s-c] run paragraph using spell
PARAS_INFO, // [s-c] paragraph runtime infos
NOTE_FORMS // set note forms
}
private static final Gson gson = new Gson();

View file

@ -86,6 +86,7 @@ public class RemoteAngularObjectTest implements AngularObjectRegistryListener {
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new GUI(),
new AngularObjectRegistry(intp.getInterpreterGroup().getId(), null),
new LocalResourcePool("pool1"),
new LinkedList<InterpreterContextRunner>(), null);

View file

@ -76,6 +76,7 @@ public class RemoteInterpreterOutputTestStream implements RemoteInterpreterProce
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new GUI(),
null,
null,
new LinkedList<InterpreterContextRunner>(), null);

View file

@ -92,7 +92,7 @@ public class RemoteInterpreterTest {
RemoteInterpreter remoteInterpreter2 = (RemoteInterpreter) interpreter2;
InterpreterContext context1 = new InterpreterContext("noteId", "paragraphId", "repl",
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(),
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(), new GUI(),
null, null, new ArrayList<InterpreterContextRunner>(), null);
assertEquals("hello", remoteInterpreter1.interpret("hello", context1).message().get(0).getData());
assertEquals(Interpreter.FormType.NATIVE, interpreter1.getFormType());
@ -135,7 +135,7 @@ public class RemoteInterpreterTest {
RemoteInterpreter remoteInterpreter2 = (RemoteInterpreter) interpreter2;
InterpreterContext context1 = new InterpreterContext("noteId", "paragraphId", "repl",
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(),
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(), new GUI(),
null, null, new ArrayList<InterpreterContextRunner>(), null);
assertEquals("hello", remoteInterpreter1.interpret("hello", context1).message().get(0).getData());
assertEquals("hello", remoteInterpreter2.interpret("hello", context1).message().get(0).getData());
@ -181,7 +181,7 @@ public class RemoteInterpreterTest {
RemoteInterpreter remoteInterpreter2 = (RemoteInterpreter) interpreter2;
InterpreterContext context1 = new InterpreterContext("noteId", "paragraphId", "repl",
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(),
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(), new GUI(),
null, null, new ArrayList<InterpreterContextRunner>(), null);
assertEquals("hello", remoteInterpreter1.interpret("hello", context1).message().get(0).getData());
assertEquals("hello", remoteInterpreter2.interpret("hello", context1).message().get(0).getData());
@ -222,7 +222,7 @@ public class RemoteInterpreterTest {
interpreterSetting.setProperty("zeppelin.SleepInterpreter.precode", "fail test");
Interpreter interpreter1 = interpreterSetting.getInterpreter("user1", "note1", "sleep");
InterpreterContext context1 = new InterpreterContext("noteId", "paragraphId", "repl",
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(),
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(), new GUI(),
null, null, new ArrayList<InterpreterContextRunner>(), null);
assertEquals(Code.ERROR, interpreter1.interpret("10", context1).code());
}
@ -233,7 +233,7 @@ public class RemoteInterpreterTest {
interpreterSetting.setProperty("zeppelin.SleepInterpreter.precode", "1");
Interpreter interpreter1 = interpreterSetting.getInterpreter("user1", "note1", "sleep");
InterpreterContext context1 = new InterpreterContext("noteId", "paragraphId", "repl",
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(),
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(), new GUI(),
null, null, new ArrayList<InterpreterContextRunner>(), null);
assertEquals(Code.SUCCESS, interpreter1.interpret("10", context1).code());
}
@ -248,7 +248,7 @@ public class RemoteInterpreterTest {
RemoteInterpreter remoteInterpreter1 = (RemoteInterpreter) interpreter1;
InterpreterContext context1 = new InterpreterContext("noteId", "paragraphId", "repl",
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(),
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(), new GUI(),
null, null, new ArrayList<InterpreterContextRunner>(), null);
assertEquals(Code.ERROR, remoteInterpreter1.interpret("hello", context1).code());
}
@ -260,7 +260,7 @@ public class RemoteInterpreterTest {
final Interpreter interpreter1 = interpreterSetting.getInterpreter("user1", "note1", "sleep");
final InterpreterContext context1 = new InterpreterContext("noteId", "paragraphId", "repl",
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(),
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(), new GUI(),
null, null, new ArrayList<InterpreterContextRunner>(), null);
// run this dummy interpret method first to launch the RemoteInterpreterProcess to avoid the
// time overhead of launching the process.
@ -303,7 +303,7 @@ public class RemoteInterpreterTest {
final Interpreter interpreter1 = interpreterSetting.getInterpreter("user1", "note1", "sleep");
final InterpreterContext context1 = new InterpreterContext("noteId", "paragraphId", "repl",
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(),
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(), new GUI(),
null, null, new ArrayList<InterpreterContextRunner>(), null);
// run this dummy interpret method first to launch the RemoteInterpreterProcess to avoid the
@ -376,7 +376,7 @@ public class RemoteInterpreterTest {
interpreter.getInterpreterGroup().setAngularObjectRegistry(registry);
final InterpreterContext context = new InterpreterContext("noteId", "paragraphId", "repl",
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(),
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(), new GUI(),
null, null, new ArrayList<InterpreterContextRunner>(), null);
InterpreterResult result = interpreter.interpret("dummy", context);
@ -403,7 +403,7 @@ public class RemoteInterpreterTest {
final Interpreter interpreter1 = interpreterSetting.getInterpreter("user1", "note1", "get");
final InterpreterContext context1 = new InterpreterContext("noteId", "paragraphId", "repl",
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(),
"title", "text", AuthenticationInfo.ANONYMOUS, new HashMap<String, Object>(), new GUI(), new GUI(),
null, null, new ArrayList<InterpreterContextRunner>(), null);
assertEquals("VALUE_1", interpreter1.interpret("getEnv ENV_1", context1).message().get(0).getData());

View file

@ -61,6 +61,7 @@ public class DistributedResourcePoolTest extends AbstractInterpreterTest {
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new GUI(),
null,
null,
new LinkedList<InterpreterContextRunner>(),

View file

@ -121,6 +121,7 @@ public class RemoteSchedulerTest implements RemoteInterpreterProcessListener {
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new GUI(),
null,
new LocalResourcePool("pool1"),
new LinkedList<InterpreterContextRunner>(), null));
@ -182,6 +183,7 @@ public class RemoteSchedulerTest implements RemoteInterpreterProcessListener {
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new GUI(),
null,
new LocalResourcePool("pool1"),
new LinkedList<InterpreterContextRunner>(), null);
@ -236,6 +238,7 @@ public class RemoteSchedulerTest implements RemoteInterpreterProcessListener {
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new GUI(),
null,
new LocalResourcePool("pool1"),
new LinkedList<InterpreterContextRunner>(), null);