mirror of
https://github.com/apache/zeppelin
synced 2026-05-24 09:38:26 +00:00
ZEPPELIN-2528. Add a password text input to the ZeppelinContext
This commit is contained in:
parent
5766c272b9
commit
084abd39c9
14 changed files with 162 additions and 24 deletions
|
|
@ -73,7 +73,7 @@ matrix:
|
|||
dist: trusty
|
||||
addons:
|
||||
firefox: "31.0"
|
||||
env: BUILD_PLUGINS="true" CI="true" PYTHON="2" SCALA_VER="2.10" SPARK_VER="1.6.3" HADOOP_VER="2.6" PROFILE="-Pspark-1.6 -Phadoop2 -Phelium-dev -Pexamples -Pintegration -Pscala-2.10" BUILD_FLAG="install -DskipTests -DskipRat" TEST_FLAG="verify -DskipRat" TEST_PROJECTS="-pl .,zeppelin-integration -DfailIfNoTests=false"
|
||||
env: BUILD_PLUGINS="true" CI="true" PYTHON="2" SCALA_VER="2.10" SPARK_VER="1.6.3" HADOOP_VER="2.6" PROFILE="-Pspark-1.6 -Phadoop2 -Phelium-dev -Pexamples -Pintegration -Pscala-2.10" BUILD_FLAG="install -DskipTests -DskipRat -pl ${INTERPRETERS}" TEST_FLAG="verify -DskipRat" TEST_PROJECTS="-pl zeppelin-integration -DfailIfNoTests=false"
|
||||
|
||||
# Test interpreter modules
|
||||
- jdk: "oraclejdk8"
|
||||
|
|
|
|||
BIN
docs/assets/themes/zeppelin/img/screenshots/form_password.png
Normal file
BIN
docs/assets/themes/zeppelin/img/screenshots/form_password.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
|
|
@ -44,6 +44,15 @@ Also you can provide default value, using `${formName=defaultValue}`.
|
|||
|
||||
<img src="{{BASE_PATH}}/assets/themes/zeppelin/img/screenshots/form_input_default.png" />
|
||||
|
||||
### Password form
|
||||
|
||||
To create password form, use `${password:formName}` templates.
|
||||
|
||||
for example
|
||||
|
||||
<img class="img-responsive" src="{{BASE_PATH}}/assets/themes/zeppelin/img/screenshots/form_password.png" />
|
||||
|
||||
|
||||
### Select form
|
||||
|
||||
To create select form, use `${formName=defaultValue,option1|option2...}`
|
||||
|
|
@ -134,6 +143,27 @@ print("Hello "+z.textbox("name", "sun"))
|
|||
</div>
|
||||
<img src="{{BASE_PATH}}/assets/themes/zeppelin/img/screenshots/form_input_default_prog.png" />
|
||||
|
||||
### Password form
|
||||
<div class="codetabs">
|
||||
<div data-lang="scala" markdown="1">
|
||||
|
||||
{% highlight scala %}
|
||||
%spark
|
||||
print("Password is "+ z.password("my_password"))
|
||||
{% endhighlight %}
|
||||
|
||||
</div>
|
||||
<div data-lang="python" markdown="1">
|
||||
|
||||
{% highlight python %}
|
||||
%pyspark
|
||||
print("Password is "+ z.password("my_password"))
|
||||
{% endhighlight %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<img src="{{BASE_PATH}}/assets/themes/zeppelin/img/screenshots/form_password_prog.png" />
|
||||
|
||||
### Select form
|
||||
<div class="codetabs">
|
||||
<div data-lang="scala" markdown="1">
|
||||
|
|
|
|||
|
|
@ -70,6 +70,9 @@ class PyZeppelinContext(object):
|
|||
def textbox(self, name, defaultValue=""):
|
||||
return self.z.textbox(name, defaultValue)
|
||||
|
||||
def password(self, name):
|
||||
return self.z.password(name)
|
||||
|
||||
def noteTextbox(self, name, defaultValue=""):
|
||||
return self.z.noteTextbox(name, defaultValue)
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
package org.apache.zeppelin.python;
|
||||
|
||||
import org.apache.zeppelin.display.ui.CheckBox;
|
||||
import org.apache.zeppelin.display.ui.Password;
|
||||
import org.apache.zeppelin.display.ui.Select;
|
||||
import org.apache.zeppelin.display.ui.TextBox;
|
||||
import org.apache.zeppelin.interpreter.Interpreter;
|
||||
|
|
@ -240,6 +241,16 @@ public abstract class BasePythonInterpreterTest {
|
|||
assertEquals("text_1", textbox.getName());
|
||||
assertEquals("value_1", textbox.getDefaultValue());
|
||||
|
||||
// Password
|
||||
context = getInterpreterContext();
|
||||
result =
|
||||
interpreter.interpret("z.password(name='pwd_1')", context);
|
||||
Thread.sleep(100);
|
||||
assertEquals(InterpreterResult.Code.SUCCESS, result.code());
|
||||
assertTrue(context.getGui().getForms().get("pwd_1") instanceof Password);
|
||||
Password password = (Password) context.getGui().getForms().get("pwd_1");
|
||||
assertEquals("pwd_1", password.getName());
|
||||
|
||||
// Select
|
||||
context = getInterpreterContext();
|
||||
result = interpreter.interpret("z.select(name='select_1'," +
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ package org.apache.zeppelin.spark;
|
|||
import com.google.common.io.Files;
|
||||
import org.apache.zeppelin.display.AngularObjectRegistry;
|
||||
import org.apache.zeppelin.display.ui.CheckBox;
|
||||
import org.apache.zeppelin.display.ui.Password;
|
||||
import org.apache.zeppelin.display.ui.Select;
|
||||
import org.apache.zeppelin.display.ui.TextBox;
|
||||
import org.apache.zeppelin.interpreter.Interpreter;
|
||||
|
|
@ -215,6 +216,14 @@ public class NewSparkInterpreterTest {
|
|||
assertEquals("name", textBox.getName());
|
||||
assertEquals("default_name", textBox.getDefaultValue());
|
||||
|
||||
context = getInterpreterContext();
|
||||
result = interpreter.interpret("z.password(\"pwd\")", context);
|
||||
assertEquals(InterpreterResult.Code.SUCCESS, result.code());
|
||||
assertEquals(1, context.getGui().getForms().size());
|
||||
assertTrue(context.getGui().getForms().get("pwd") instanceof Password);
|
||||
Password pwd = (Password) context.getGui().getForms().get("pwd");
|
||||
assertEquals("pwd", pwd.getName());
|
||||
|
||||
context = getInterpreterContext();
|
||||
result = interpreter.interpret("z.checkbox(\"checkbox_1\", Seq(\"value_2\"), Seq((\"value_1\", \"name_1\"), (\"value_2\", \"name_2\")))", context);
|
||||
assertEquals(InterpreterResult.Code.SUCCESS, result.code());
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import com.google.gson.Gson;
|
|||
import com.google.gson.GsonBuilder;
|
||||
import org.apache.zeppelin.display.ui.CheckBox;
|
||||
import org.apache.zeppelin.display.ui.OptionInput.ParamOption;
|
||||
import org.apache.zeppelin.display.ui.Password;
|
||||
import org.apache.zeppelin.display.ui.Select;
|
||||
import org.apache.zeppelin.display.ui.TextBox;
|
||||
|
||||
|
|
@ -90,6 +91,11 @@ public class GUI implements Serializable {
|
|||
return textbox(id, "");
|
||||
}
|
||||
|
||||
public Object password(String id) {
|
||||
forms.put(id, new Password(id));
|
||||
return params.get(id);
|
||||
}
|
||||
|
||||
public Object select(String id, Object defaultValue, ParamOption[] options) {
|
||||
if (defaultValue == null && options != null && options.length > 0) {
|
||||
defaultValue = options[0].getValue();
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import org.apache.commons.lang.StringUtils;
|
|||
import org.apache.zeppelin.display.ui.CheckBox;
|
||||
import org.apache.zeppelin.display.ui.OptionInput;
|
||||
import org.apache.zeppelin.display.ui.OptionInput.ParamOption;
|
||||
import org.apache.zeppelin.display.ui.Password;
|
||||
import org.apache.zeppelin.display.ui.Select;
|
||||
import org.apache.zeppelin.display.ui.TextBox;
|
||||
|
||||
|
|
@ -49,6 +50,7 @@ public class Input<T> implements Serializable {
|
|||
.registerSubtype(TextBox.class, "TextBox")
|
||||
.registerSubtype(Select.class, "Select")
|
||||
.registerSubtype(CheckBox.class, "CheckBox")
|
||||
.registerSubtype(Password.class, "Password")
|
||||
.registerSubtype(OldInput.OldTextBox.class, "input")
|
||||
.registerSubtype(OldInput.OldSelect.class, "select")
|
||||
.registerSubtype(OldInput.OldCheckBox.class, "checkbox")
|
||||
|
|
@ -282,6 +284,8 @@ public class Input<T> implements Serializable {
|
|||
}
|
||||
} else if (type.equals("checkbox")) {
|
||||
input = new CheckBox(varName, (Object[]) defaultValue, paramOptions);
|
||||
} else if (type.equals("password")) {
|
||||
input = new Password(varName);
|
||||
} else {
|
||||
throw new RuntimeException("Could not recognize dynamic form with type: " + type);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.apache.zeppelin.display.ui;
|
||||
|
||||
import org.apache.zeppelin.display.Input;
|
||||
|
||||
public class Password extends Input<String> {
|
||||
|
||||
public Password() {
|
||||
|
||||
}
|
||||
|
||||
public Password(String name) {
|
||||
this.name = name;
|
||||
this.displayName = name;
|
||||
this.defaultValue = "";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -102,6 +102,20 @@ public abstract class BaseZeppelinContext {
|
|||
return textbox(name, defaultValue, false);
|
||||
}
|
||||
|
||||
@ZeppelinApi
|
||||
public Object password(String name) {
|
||||
return password(name, false);
|
||||
}
|
||||
|
||||
@ZeppelinApi
|
||||
public Object password(String name, boolean noteForm) {
|
||||
if (noteForm) {
|
||||
return noteGui.password(name);
|
||||
} else {
|
||||
return gui.password(name);
|
||||
}
|
||||
}
|
||||
|
||||
@ZeppelinApi
|
||||
public Collection<Object> checkbox(String name, ParamOption[] options) {
|
||||
return checkbox(name, options, false);
|
||||
|
|
|
|||
|
|
@ -19,10 +19,9 @@ package org.apache.zeppelin.display;
|
|||
|
||||
import org.apache.zeppelin.display.ui.CheckBox;
|
||||
import org.apache.zeppelin.display.ui.OptionInput.ParamOption;
|
||||
import org.apache.zeppelin.display.ui.Password;
|
||||
import org.apache.zeppelin.display.ui.Select;
|
||||
import org.apache.zeppelin.display.ui.TextBox;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
|
@ -35,14 +34,6 @@ import static org.junit.Assert.assertTrue;
|
|||
|
||||
public class InputTest {
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormExtraction() {
|
||||
// textbox form
|
||||
|
|
@ -61,12 +52,21 @@ public class InputTest {
|
|||
form = forms.get("input_form");
|
||||
assertEquals("xxx", form.defaultValue);
|
||||
assertTrue(form instanceof TextBox);
|
||||
assertEquals("Input Form", form.getDisplayName());
|
||||
|
||||
// password form with display name
|
||||
script = "${password:my_pwd(My Password)}";
|
||||
forms = Input.extractSimpleQueryForm(script, false);
|
||||
form = forms.get("my_pwd");
|
||||
assertTrue(form instanceof Password);
|
||||
assertEquals("My Password", form.getDisplayName());
|
||||
|
||||
// selection form
|
||||
script = "${select_form(Selection Form)=op1,op1|op2(Option 2)|op3}";
|
||||
form = Input.extractSimpleQueryForm(script, false).get("select_form");
|
||||
assertEquals("select_form", form.name);
|
||||
assertEquals("op1", form.defaultValue);
|
||||
assertEquals("Selection Form", form.getDisplayName());
|
||||
assertTrue(form instanceof Select);
|
||||
assertArrayEquals(new ParamOption[]{
|
||||
new ParamOption("op1", null),
|
||||
|
|
|
|||
|
|
@ -499,6 +499,7 @@ public class ZeppelinSparkClusterTest extends AbstractTestRestApi {
|
|||
Note note = ZeppelinServer.notebook.createNote(anonymous);
|
||||
Paragraph p = note.addNewParagraph(anonymous);
|
||||
String code = "%spark.spark println(z.textbox(\"my_input\", \"default_name\"))\n" +
|
||||
"println(z.password(\"my_pwd\"))\n" +
|
||||
"println(z.select(\"my_select\", \"1\"," +
|
||||
"Seq((\"1\", \"select_1\"), (\"2\", \"select_2\"))))\n" +
|
||||
"val items=z.checkbox(\"my_checkbox\", Seq(\"2\"), " +
|
||||
|
|
@ -510,17 +511,19 @@ public class ZeppelinSparkClusterTest extends AbstractTestRestApi {
|
|||
|
||||
assertEquals(Status.FINISHED, p.getStatus());
|
||||
Iterator<String> formIter = p.settings.getForms().keySet().iterator();
|
||||
assert (formIter.next().equals("my_input"));
|
||||
assert (formIter.next().equals("my_select"));
|
||||
assert (formIter.next().equals("my_checkbox"));
|
||||
assertEquals("my_input", formIter.next());
|
||||
assertEquals("my_pwd", formIter.next());
|
||||
assertEquals("my_select", formIter.next());
|
||||
assertEquals("my_checkbox", formIter.next());
|
||||
|
||||
// check dynamic forms values
|
||||
String[] result = p.getResult().message().get(0).getData().split("\n");
|
||||
assertEquals(4, result.length);
|
||||
assertEquals(5, result.length);
|
||||
assertEquals("default_name", result[0]);
|
||||
assertEquals("1", result[1]);
|
||||
assertEquals("items: Seq[Object] = Buffer(2)", result[2]);
|
||||
assertEquals("2", result[3]);
|
||||
assertEquals("null", result[1]);
|
||||
assertEquals("1", result[2]);
|
||||
assertEquals("items: Seq[Object] = Buffer(2)", result[3]);
|
||||
assertEquals("2", result[4]);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -528,6 +531,7 @@ public class ZeppelinSparkClusterTest extends AbstractTestRestApi {
|
|||
Note note = ZeppelinServer.notebook.createNote(anonymous);
|
||||
Paragraph p = note.addNewParagraph(anonymous);
|
||||
String code = "%spark.pyspark print(z.input('my_input', 'default_name'))\n" +
|
||||
"print(z.password('my_pwd'))\n" +
|
||||
"print(z.select('my_select', " +
|
||||
"[('1', 'select_1'), ('2', 'select_2')], defaultValue='1'))\n" +
|
||||
"items=z.checkbox('my_checkbox', " +
|
||||
|
|
@ -538,16 +542,18 @@ public class ZeppelinSparkClusterTest extends AbstractTestRestApi {
|
|||
|
||||
assertEquals(Status.FINISHED, p.getStatus());
|
||||
Iterator<String> formIter = p.settings.getForms().keySet().iterator();
|
||||
assert (formIter.next().equals("my_input"));
|
||||
assert (formIter.next().equals("my_select"));
|
||||
assert (formIter.next().equals("my_checkbox"));
|
||||
assertEquals("my_input", formIter.next());
|
||||
assertEquals("my_pwd", formIter.next());
|
||||
assertEquals("my_select", formIter.next());
|
||||
assertEquals("my_checkbox", formIter.next());
|
||||
|
||||
// check dynamic forms values
|
||||
String[] result = p.getResult().message().get(0).getData().split("\n");
|
||||
assertEquals(3, result.length);
|
||||
assertEquals(4, result.length);
|
||||
assertEquals("default_name", result[0]);
|
||||
assertEquals("1", result[1]);
|
||||
assertEquals("2", result[2]);
|
||||
assertEquals("None", result[1]);
|
||||
assertEquals("1", result[2]);
|
||||
assertEquals("2", result[3]);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -41,6 +41,25 @@ limitations under the License.
|
|||
ng-class="{'disable': disable}"
|
||||
name="{{formulaire.name}}" />
|
||||
</div>
|
||||
<div ng-if="actiononchange === true">
|
||||
<input class="form-control input-sm"
|
||||
ng-if="forms[formulaire.name].type == 'Password'"
|
||||
ng-change="action()"
|
||||
ng-model-options='{ debounce: 1000 }'
|
||||
ng-model="params[formulaire.name]"
|
||||
ng-class="{'disable': disable}"
|
||||
type="password"
|
||||
name="{{formulaire.name}}" />
|
||||
</div>
|
||||
<div ng-if="!actiononchange">
|
||||
<input class="form-control input-sm"
|
||||
ng-if="forms[formulaire.name].type == 'Password'"
|
||||
ng-enter="action()"
|
||||
ng-model="params[formulaire.name]"
|
||||
ng-class="{'disable': disable}"
|
||||
type="password"
|
||||
name="{{formulaire.name}}" />
|
||||
</div>
|
||||
<div ng-if="actiononchange === true">
|
||||
<select class="form-control input-sm"
|
||||
ng-if="forms[formulaire.name].type == 'Select'"
|
||||
|
|
|
|||
Loading…
Reference in a new issue