You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zeppelin.apache.org by zj...@apache.org on 2018/06/28 01:56:53 UTC

zeppelin git commit: ZEPPELIN-2528. Add a password text input to the ZeppelinContext

Repository: zeppelin
Updated Branches:
  refs/heads/master 5766c272b -> 5e33f2c98


ZEPPELIN-2528. Add a password text input to the ZeppelinContext

### What is this PR for?
This is to add password for dynamic forms. It is almost the same as input box but but with invisible input. And there's no default value for password form, as it doesn't make sense to provide default value for password.

### What type of PR is it?
[ Feature ]

### Todos
* [ ] - Task

### What is the Jira issue?
* https://issues.apache.org/jira/browse/ZEPPELIN-2528

### How should this be tested?
* CI pass

### Screenshots (if appropriate)

![form_password_prog](https://user-images.githubusercontent.com/164491/41765448-aee6188e-7636-11e8-867b-ad766ee4188f.png)
![form_password](https://user-images.githubusercontent.com/164491/41765449-af151ba2-7636-11e8-8f2b-6f16dfde96b7.png)

### Questions:
* Does the licenses files need update? No
* Is there breaking changes for older versions? No
* Does this needs documentation? No

Author: Jeff Zhang <zj...@apache.org>

Closes #3041 from zjffdu/ZEPPELIN-2528 and squashes the following commits:

084abd39c [Jeff Zhang] ZEPPELIN-2528. Add a password text input to the ZeppelinContext


Project: http://git-wip-us.apache.org/repos/asf/zeppelin/repo
Commit: http://git-wip-us.apache.org/repos/asf/zeppelin/commit/5e33f2c9
Tree: http://git-wip-us.apache.org/repos/asf/zeppelin/tree/5e33f2c9
Diff: http://git-wip-us.apache.org/repos/asf/zeppelin/diff/5e33f2c9

Branch: refs/heads/master
Commit: 5e33f2c98d3b43b81df3d13d597d739b264405ec
Parents: 5766c27
Author: Jeff Zhang <zj...@apache.org>
Authored: Fri Jun 22 14:37:17 2018 +0800
Committer: Jeff Zhang <zj...@apache.org>
Committed: Thu Jun 28 09:56:48 2018 +0800

----------------------------------------------------------------------
 .travis.yml                                     |   2 +-
 .../zeppelin/img/screenshots/form_password.png  | Bin 0 -> 29067 bytes
 .../img/screenshots/form_password_prog.png      | Bin 0 -> 34717 bytes
 docs/usage/dynamic_form/intro.md                |  30 ++++++++++++++++
 .../main/resources/python/zeppelin_context.py   |   3 ++
 .../python/BasePythonInterpreterTest.java       |  11 ++++++
 .../zeppelin/spark/NewSparkInterpreterTest.java |   9 +++++
 .../java/org/apache/zeppelin/display/GUI.java   |   6 ++++
 .../java/org/apache/zeppelin/display/Input.java |   4 +++
 .../apache/zeppelin/display/ui/Password.java    |  36 +++++++++++++++++++
 .../interpreter/BaseZeppelinContext.java        |  14 ++++++++
 .../org/apache/zeppelin/display/InputTest.java  |  20 +++++------
 .../zeppelin/rest/ZeppelinSparkClusterTest.java |  32 ++++++++++-------
 .../dynamic-forms/dynamic-forms.directive.html  |  19 ++++++++++
 14 files changed, 162 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5e33f2c9/.travis.yml
----------------------------------------------------------------------
diff --git a/.travis.yml b/.travis.yml
index 1227876..7c10987 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -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"

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5e33f2c9/docs/assets/themes/zeppelin/img/screenshots/form_password.png
----------------------------------------------------------------------
diff --git a/docs/assets/themes/zeppelin/img/screenshots/form_password.png b/docs/assets/themes/zeppelin/img/screenshots/form_password.png
new file mode 100644
index 0000000..5b4eb72
Binary files /dev/null and b/docs/assets/themes/zeppelin/img/screenshots/form_password.png differ

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5e33f2c9/docs/assets/themes/zeppelin/img/screenshots/form_password_prog.png
----------------------------------------------------------------------
diff --git a/docs/assets/themes/zeppelin/img/screenshots/form_password_prog.png b/docs/assets/themes/zeppelin/img/screenshots/form_password_prog.png
new file mode 100644
index 0000000..40f15e6
Binary files /dev/null and b/docs/assets/themes/zeppelin/img/screenshots/form_password_prog.png differ

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5e33f2c9/docs/usage/dynamic_form/intro.md
----------------------------------------------------------------------
diff --git a/docs/usage/dynamic_form/intro.md b/docs/usage/dynamic_form/intro.md
index 1da5876..3f1b9fe 100644
--- a/docs/usage/dynamic_form/intro.md
+++ b/docs/usage/dynamic_form/intro.md
@@ -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">

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5e33f2c9/python/src/main/resources/python/zeppelin_context.py
----------------------------------------------------------------------
diff --git a/python/src/main/resources/python/zeppelin_context.py b/python/src/main/resources/python/zeppelin_context.py
index d29a16f..dc97c14 100644
--- a/python/src/main/resources/python/zeppelin_context.py
+++ b/python/src/main/resources/python/zeppelin_context.py
@@ -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)
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5e33f2c9/python/src/test/java/org/apache/zeppelin/python/BasePythonInterpreterTest.java
----------------------------------------------------------------------
diff --git a/python/src/test/java/org/apache/zeppelin/python/BasePythonInterpreterTest.java b/python/src/test/java/org/apache/zeppelin/python/BasePythonInterpreterTest.java
index 9697fbf..25cb253 100644
--- a/python/src/test/java/org/apache/zeppelin/python/BasePythonInterpreterTest.java
+++ b/python/src/test/java/org/apache/zeppelin/python/BasePythonInterpreterTest.java
@@ -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'," +

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5e33f2c9/spark/interpreter/src/test/java/org/apache/zeppelin/spark/NewSparkInterpreterTest.java
----------------------------------------------------------------------
diff --git a/spark/interpreter/src/test/java/org/apache/zeppelin/spark/NewSparkInterpreterTest.java b/spark/interpreter/src/test/java/org/apache/zeppelin/spark/NewSparkInterpreterTest.java
index 65b739d..73bd52c 100644
--- a/spark/interpreter/src/test/java/org/apache/zeppelin/spark/NewSparkInterpreterTest.java
+++ b/spark/interpreter/src/test/java/org/apache/zeppelin/spark/NewSparkInterpreterTest.java
@@ -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;
@@ -216,6 +217,14 @@ public class NewSparkInterpreterTest {
     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());
     assertEquals(1, context.getGui().getForms().size());

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5e33f2c9/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/GUI.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/GUI.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/GUI.java
index 5657c58..048ee81 100644
--- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/GUI.java
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/GUI.java
@@ -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();

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5e33f2c9/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/Input.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/Input.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/Input.java
index 51e27d2..40878a8 100644
--- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/Input.java
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/Input.java
@@ -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);
     }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5e33f2c9/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/ui/Password.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/ui/Password.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/ui/Password.java
new file mode 100644
index 0000000..e3fd624
--- /dev/null
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/display/ui/Password.java
@@ -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 = "";
+  }
+
+}
+

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5e33f2c9/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/BaseZeppelinContext.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/BaseZeppelinContext.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/BaseZeppelinContext.java
index dba9471..04f6c70 100644
--- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/BaseZeppelinContext.java
+++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/BaseZeppelinContext.java
@@ -103,6 +103,20 @@ public abstract class BaseZeppelinContext {
   }
 
   @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);
   }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5e33f2c9/zeppelin-interpreter/src/test/java/org/apache/zeppelin/display/InputTest.java
----------------------------------------------------------------------
diff --git a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/display/InputTest.java b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/display/InputTest.java
index a9252b9..abe2ac3 100644
--- a/zeppelin-interpreter/src/test/java/org/apache/zeppelin/display/InputTest.java
+++ b/zeppelin-interpreter/src/test/java/org/apache/zeppelin/display/InputTest.java
@@ -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),

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5e33f2c9/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinSparkClusterTest.java
----------------------------------------------------------------------
diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinSparkClusterTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinSparkClusterTest.java
index edfbc65..fdb41a4 100644
--- a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinSparkClusterTest.java
+++ b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinSparkClusterTest.java
@@ -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

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5e33f2c9/zeppelin-web/src/app/notebook/dynamic-forms/dynamic-forms.directive.html
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/app/notebook/dynamic-forms/dynamic-forms.directive.html b/zeppelin-web/src/app/notebook/dynamic-forms/dynamic-forms.directive.html
index f9f6028..e73f9f8 100644
--- a/zeppelin-web/src/app/notebook/dynamic-forms/dynamic-forms.directive.html
+++ b/zeppelin-web/src/app/notebook/dynamic-forms/dynamic-forms.directive.html
@@ -42,6 +42,25 @@ limitations under the License.
              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'"
               ng-change="action()"