Repository: zeppelin Updated Branches: refs/heads/master 824fd955f -> 60089f0f5
[ZEPPELIN-1566] Make paragraph editable with double click ### What is this PR for? This PR enables edit on double click for markdown/angular paragraph. Users can change `editOnDblClick` field to be `false` by editting `interpreter/md/interpreter-setting.json` or `conf/interpreter.json`. In the same context, users can set other type paragraphs to be editable on double click by setting `editOnDblClick` to be true. This PR also fixes bug that syntax highlight doesn't work on pasted code. ### What type of PR is it? Feature ### Todos * [x] Create test * [x] Update docs ### What is the Jira issue? [ZEPPELIN-1566](https://issues.apache.org/jira/browse/ZEPPELIN-1566) ### How should this be tested? 1. Create new markdown interpreter 2. Create notebook and run markdown paragraph 3. Double click markdown paragraph to edit ### Screenshots (if appropriate) **Edit on double click and hide editor on paragraph run**  **Syntax highlight on paste** Before  After  ### Questions: * Does the licenses files need update? no * Is there breaking changes for older versions? no * Does this needs documentation? yes Author: Mina Lee <[email protected]> Closes #1540 from minahlee/ZEPPELIN-1566 and squashes the following commits: 89ea628 [Mina Lee] Remove redundant code 4ffc446 [Mina Lee] Enable focus first paragraph on note reload c566706 [Mina Lee] Check null condition of editor setting and return default setting 38d5e35 [Mina Lee] Update document about how to make paragraph editable on double click b42039e [Mina Lee] Add integration test for editOnDblClick 0a26207 [Mina Lee] Add editOnDblClick field in interpreter-setting.json 93abe6a [Mina Lee] Make paragraph editable on doubleclick if editOnDblClick set true in interpreter-setting.json 359dc0b [Mina Lee] Split getAndSetEditorSetting method into getEditorSetting and setEditorLanguage method Project: http://git-wip-us.apache.org/repos/asf/zeppelin/repo Commit: http://git-wip-us.apache.org/repos/asf/zeppelin/commit/60089f0f Tree: http://git-wip-us.apache.org/repos/asf/zeppelin/tree/60089f0f Diff: http://git-wip-us.apache.org/repos/asf/zeppelin/diff/60089f0f Branch: refs/heads/master Commit: 60089f0f5801562c104b8822dabfedc889611abc Parents: 824fd95 Author: Mina Lee <[email protected]> Authored: Fri Oct 28 13:21:01 2016 +0900 Committer: Mina Lee <[email protected]> Committed: Sat Oct 29 10:30:22 2016 +0900 ---------------------------------------------------------------------- .../src/main/resources/interpreter-setting.json | 5 +- .../src/main/resources/interpreter-setting.json | 4 +- .../src/main/resources/interpreter-setting.json | 4 +- .../src/main/resources/interpreter-setting.json | 3 +- .../src/main/resources/interpreter-setting.json | 3 + docs/development/writingzeppelininterpreter.md | 34 ++++-- docs/install/install.md | 4 +- .../src/main/resources/interpreter-setting.json | 3 + .../src/main/resources/interpreter-setting.json | 3 + .../src/main/resources/interpreter-setting.json | 3 +- .../src/main/resources/interpreter-setting.json | 3 + .../src/main/resources/interpreter-setting.json | 3 +- .../src/main/resources/interpreter-setting.json | 3 +- .../src/main/resources/interpreter-setting.json | 12 ++- .../src/main/resources/interpreter-setting.json | 3 +- pig/src/main/resources/interpreter-setting.json | 6 +- .../src/main/resources/interpreter-setting.json | 10 +- .../src/main/resources/interpreter-setting.json | 3 +- .../src/main/resources/interpreter-setting.json | 12 ++- .../integration/ParagraphActionsIT.java | 46 ++++++++ .../src/app/notebook/notebook.controller.js | 4 + zeppelin-web/src/app/notebook/notebook.html | 3 +- .../notebook/paragraph/paragraph.controller.js | 104 ++++++++++++++----- .../src/app/notebook/paragraph/paragraph.html | 3 +- .../interpreter/InterpreterFactory.java | 16 ++- 25 files changed, 230 insertions(+), 67 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/alluxio/src/main/resources/interpreter-setting.json ---------------------------------------------------------------------- diff --git a/alluxio/src/main/resources/interpreter-setting.json b/alluxio/src/main/resources/interpreter-setting.json index 7bae20b..8b082ab 100644 --- a/alluxio/src/main/resources/interpreter-setting.json +++ b/alluxio/src/main/resources/interpreter-setting.json @@ -16,6 +16,9 @@ "defaultValue": "19998", "description": "Alluxio master port" } + }, + "editor": { + "editOnDblClick": false } } -] \ No newline at end of file +] http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/angular/src/main/resources/interpreter-setting.json ---------------------------------------------------------------------- diff --git a/angular/src/main/resources/interpreter-setting.json b/angular/src/main/resources/interpreter-setting.json index 9e379de..4ff5978 100644 --- a/angular/src/main/resources/interpreter-setting.json +++ b/angular/src/main/resources/interpreter-setting.json @@ -4,7 +4,9 @@ "name": "angular", "className": "org.apache.zeppelin.angular.AngularInterpreter", "properties": { - + }, + "editor": { + "editOnDblClick": true } } ] http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/beam/src/main/resources/interpreter-setting.json ---------------------------------------------------------------------- diff --git a/beam/src/main/resources/interpreter-setting.json b/beam/src/main/resources/interpreter-setting.json index 7cf57d2..189e08b 100644 --- a/beam/src/main/resources/interpreter-setting.json +++ b/beam/src/main/resources/interpreter-setting.json @@ -5,7 +5,9 @@ "className": "org.apache.zeppelin.beam.BeamInterpreter", "defaultInterpreter": true, "properties": { - + }, + "editor": { + "editOnDblClick": false } } ] http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/bigquery/src/main/resources/interpreter-setting.json ---------------------------------------------------------------------- diff --git a/bigquery/src/main/resources/interpreter-setting.json b/bigquery/src/main/resources/interpreter-setting.json index fb44063..b99a763 100644 --- a/bigquery/src/main/resources/interpreter-setting.json +++ b/bigquery/src/main/resources/interpreter-setting.json @@ -24,7 +24,8 @@ } }, "editor": { - "language": "sql" + "language": "sql", + "editOnDblClick": false } } ] http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/cassandra/src/main/resources/interpreter-setting.json ---------------------------------------------------------------------- diff --git a/cassandra/src/main/resources/interpreter-setting.json b/cassandra/src/main/resources/interpreter-setting.json index eb98472..3df120d 100644 --- a/cassandra/src/main/resources/interpreter-setting.json +++ b/cassandra/src/main/resources/interpreter-setting.json @@ -190,6 +190,9 @@ "defaultValue": "true", "description": "Cassandra socket TCP no delay. Default = true" } + }, + "editor": { + "editOnDblClick": false } } ] http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/docs/development/writingzeppelininterpreter.md ---------------------------------------------------------------------- diff --git a/docs/development/writingzeppelininterpreter.md b/docs/development/writingzeppelininterpreter.md index acf72e8..c5fb23c 100644 --- a/docs/development/writingzeppelininterpreter.md +++ b/docs/development/writingzeppelininterpreter.md @@ -34,7 +34,7 @@ Interpreters in the same InterpreterGroup can reference each other. For example, [InterpreterSetting](https://github.com/apache/zeppelin/blob/master/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterSetting.java) is configuration of a given [InterpreterGroup](https://github.com/apache/zeppelin/blob/master/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/InterpreterGroup.java) and a unit of start/stop interpreter. All Interpreters in the same InterpreterSetting are launched in a single, separate JVM process. The Interpreter communicates with Zeppelin engine via **[Thrift](https://github.com/apache/zeppelin/blob/master/zeppelin-interpreter/src/main/thrift/RemoteInterpreterService.thrift)**. -In 'Separate Interpreter(scoped / isolated) for each note' mode which you can see at the **Interpreter Setting** menu when you create a new interpreter, new interpreter instance will be created per notebook. But it still runs on the same JVM while they're in the same InterpreterSettings. +In 'Separate Interpreter(scoped / isolated) for each note' mode which you can see at the **Interpreter Setting** menu when you create a new interpreter, new interpreter instance will be created per note. But it still runs on the same JVM while they're in the same InterpreterSettings. ## Make your own Interpreter @@ -48,7 +48,7 @@ There are three locations where you can store your interpreter group, name and o {ZEPPELIN_INTERPRETER_DIR}/{YOUR_OWN_INTERPRETER_DIR}/interpreter-setting.json ``` -Here is an example of `interpreter-setting.json` on your own interpreter. Note that if you don't specify editor object, your interpreter will use plain text mode for syntax highlighting. +Here is an example of `interpreter-setting.json` on your own interpreter. ```json [ @@ -71,7 +71,8 @@ Here is an example of `interpreter-setting.json` on your own interpreter. Note t }, ... }, "editor": { - "language": "your-syntax-highlight-language" + "language": "your-syntax-highlight-language", + "editOnDblClick": false } }, { @@ -98,15 +99,18 @@ The name of the interpreter is what you later write to identify a paragraph whic some interpreter specific code... ``` -## Programming Languages for Interpreter -If the interpreter uses a specific programming language (like Scala, Python, SQL), it is generally recommended to add a syntax highlighting supported for that to the notebook paragraph editor. +## Editor setting for Interpreter +You can add `editor` object to `interpreter-setting.json` file to specify paragraph editor settings. -To check out the list of languages supported, see the `mode-*.js` files under `zeppelin-web/bower_components/ace-builds/src-noconflict` or from [github.com/ajaxorg/ace-builds](https://github.com/ajaxorg/ace-builds/tree/master/src-noconflict). +### Language +If the interpreter uses a specific programming language (like Scala, Python, SQL), it is generally recommended to add a syntax highlighting supported for that to the note paragraph editor. + +To check out the list of languages supported, see the `mode-*.js` files under `zeppelin-web/bower_components/ace-builds/src-noconflict` or from [github.com/ajaxorg/ace-builds](https://github.com/ajaxorg/ace-builds/tree/master/src-noconflict). If you want to add a new set of syntax highlighting, -1. Add the `mode-*.js` file to <code>[zeppelin-web/bower.json](https://github.com/apache/zeppelin/blob/master/zeppelin-web/bower.json)</code> ( when built, <code>[zeppelin-web/src/index.html](https://github.com/apache/zeppelin/blob/master/zeppelin-web/src/index.html)</code> will be changed automatically. ). -2. Add `editor` object to `interpreter-setting.json` file. If you want to set your language to `java` for example, add: +1. Add the `mode-*.js` file to <code>[zeppelin-web/bower.json](https://github.com/apache/zeppelin/blob/master/zeppelin-web/bower.json)</code> (when built, <code>[zeppelin-web/src/index.html](https://github.com/apache/zeppelin/blob/master/zeppelin-web/src/index.html)</code> will be changed automatically). +2. Add `language` field to `editor` object. Note that if you don't specify language field, your interpreter will use plain text mode for syntax highlighting. Let's say you want to set your language to `java`, then add: ``` "editor": { @@ -114,6 +118,14 @@ If you want to add a new set of syntax highlighting, } ``` +### Edit on double click +If your interpreter uses mark-up language such as markdown or HTML, set `editOnDblClick` to `true` so that text editor opens on pargraph double click and closes on paragraph run. Otherwise set it to `false`. + +``` +"editor": { + "editOnDblClick": false +} +``` ## Install your interpreter binary Once you have built your interpreter, you can place it under the interpreter directory with all its dependencies. @@ -150,7 +162,7 @@ Now you are done and ready to use your interpreter. ## Use your interpreter ### 0.5.0 -Inside of a notebook, `%[INTERPRETER_NAME]` directive will call your interpreter. +Inside of a note, `%[INTERPRETER_NAME]` directive will call your interpreter. Note that the first interpreter configuration in zeppelin.interpreters will be the default one. For example, @@ -163,7 +175,7 @@ println(a) ``` ### 0.6.0 and later -Inside of a notebook, `%[INTERPRETER_GROUP].[INTERPRETER_NAME]` directive will call your interpreter. +Inside of a note, `%[INTERPRETER_GROUP].[INTERPRETER_NAME]` directive will call your interpreter. You can omit either [INTERPRETER\_GROUP] or [INTERPRETER\_NAME]. If you omit [INTERPRETER\_NAME], then first available interpreter will be selected in the [INTERPRETER\_GROUP]. Likewise, if you skip [INTERPRETER\_GROUP], then [INTERPRETER\_NAME] will be chosen from default interpreter group. @@ -216,7 +228,7 @@ Checkout some interpreters released with Zeppelin by default. We welcome contribution to a new interpreter. Please follow these few steps: - First, check out the general contribution guide [here](https://zeppelin.apache.org/contribution/contributions.html). - - Follow the steps in [Make your own Interpreter](#make-your-own-interpreter) section above. + - Follow the steps in [Make your own Interpreter](#make-your-own-interpreter) section and [Editor setting for Interpreter](#editor-setting-for-interpreter) above. - Add your interpreter as in the [Configure your interpreter](#configure-your-interpreter) section above; also add it to the example template [zeppelin-site.xml.template](https://github.com/apache/zeppelin/blob/master/conf/zeppelin-site.xml.template). - Add tests! They are run by [Travis](https://travis-ci.org/apache/zeppelin) for all changes and it is important that they are self-contained. - Include your interpreter as a module in [`pom.xml`](https://github.com/apache/zeppelin/blob/master/pom.xml). http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/docs/install/install.md ---------------------------------------------------------------------- diff --git a/docs/install/install.md b/docs/install/install.md index e14fc7c..43416dc 100644 --- a/docs/install/install.md +++ b/docs/install/install.md @@ -55,7 +55,7 @@ Stable binary packages are available on the [Apache Zeppelin Download Page](http If you downloaded the default package, just unpack it in a directory of your choice and you're ready to go. If you downloaded the *net-install* package, you should manually [install additional interpreters](../manual/interpreterinstallation.html) first. You can also install everything by running `./bin/install-interpreter.sh --all`. -After unpacking, jump to the [Starting Apache Zeppelin with Command Line](#starting-apache-zeppelin-with-command-line). +After unpacking, jump to the [Starting Apache Zeppelin from Command Line](#starting-apache-zeppelin-from-the-command-line). ### Building from Source @@ -178,7 +178,7 @@ chdir /usr/share/zeppelin exec bin/zeppelin-daemon.sh upstart ``` -## Next Steps: +## Next Steps Congratulations, you have successfully installed Apache Zeppelin! Here are two next steps you might find useful: http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/elasticsearch/src/main/resources/interpreter-setting.json ---------------------------------------------------------------------- diff --git a/elasticsearch/src/main/resources/interpreter-setting.json b/elasticsearch/src/main/resources/interpreter-setting.json index 16a207e..089c811 100644 --- a/elasticsearch/src/main/resources/interpreter-setting.json +++ b/elasticsearch/src/main/resources/interpreter-setting.json @@ -28,6 +28,9 @@ "defaultValue": "10", "description": "The size of the result set of a search query" } + }, + "editor": { + "editOnDblClick": false } } ] http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/file/src/main/resources/interpreter-setting.json ---------------------------------------------------------------------- diff --git a/file/src/main/resources/interpreter-setting.json b/file/src/main/resources/interpreter-setting.json index 85ff746..b4f9199 100644 --- a/file/src/main/resources/interpreter-setting.json +++ b/file/src/main/resources/interpreter-setting.json @@ -22,6 +22,9 @@ "defaultValue": "1000", "description": "Maximum number of lines of results fetched" } + }, + "editor": { + "editOnDblClick": false } } ] http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/flink/src/main/resources/interpreter-setting.json ---------------------------------------------------------------------- diff --git a/flink/src/main/resources/interpreter-setting.json b/flink/src/main/resources/interpreter-setting.json index e9bd126..0d4cf6b 100644 --- a/flink/src/main/resources/interpreter-setting.json +++ b/flink/src/main/resources/interpreter-setting.json @@ -18,7 +18,8 @@ } }, "editor": { - "language": "scala" + "language": "scala", + "editOnDblClick": false } } ] http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/hbase/src/main/resources/interpreter-setting.json ---------------------------------------------------------------------- diff --git a/hbase/src/main/resources/interpreter-setting.json b/hbase/src/main/resources/interpreter-setting.json index be2f01a..aa44295 100644 --- a/hbase/src/main/resources/interpreter-setting.json +++ b/hbase/src/main/resources/interpreter-setting.json @@ -20,6 +20,9 @@ "defaultValue": "false", "description": "Disable checks for unit and manual tests" } + }, + "editor": { + "editOnDblClick": false } } ] http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/jdbc/src/main/resources/interpreter-setting.json ---------------------------------------------------------------------- diff --git a/jdbc/src/main/resources/interpreter-setting.json b/jdbc/src/main/resources/interpreter-setting.json index 6809915..20a900f 100644 --- a/jdbc/src/main/resources/interpreter-setting.json +++ b/jdbc/src/main/resources/interpreter-setting.json @@ -66,7 +66,8 @@ } }, "editor": { - "language": "sql" + "language": "sql", + "editOnDblClick": false } } ] http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/kylin/src/main/resources/interpreter-setting.json ---------------------------------------------------------------------- diff --git a/kylin/src/main/resources/interpreter-setting.json b/kylin/src/main/resources/interpreter-setting.json index b804da0..ca51b17 100644 --- a/kylin/src/main/resources/interpreter-setting.json +++ b/kylin/src/main/resources/interpreter-setting.json @@ -48,7 +48,8 @@ } }, "editor": { - "language": "sql" + "language": "sql", + "editOnDblClick": false } } ] http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/livy/src/main/resources/interpreter-setting.json ---------------------------------------------------------------------- diff --git a/livy/src/main/resources/interpreter-setting.json b/livy/src/main/resources/interpreter-setting.json index 4f2cf3d..0c28e40 100644 --- a/livy/src/main/resources/interpreter-setting.json +++ b/livy/src/main/resources/interpreter-setting.json @@ -94,7 +94,8 @@ } }, "editor": { - "language": "scala" + "language": "scala", + "editOnDblClick": false } }, { @@ -115,7 +116,8 @@ } }, "editor": { - "language": "sql" + "language": "sql", + "editOnDblClick": false } }, { @@ -125,7 +127,8 @@ "properties": { }, "editor": { - "language": "python" + "language": "python", + "editOnDblClick": false } }, { @@ -135,7 +138,8 @@ "properties": { }, "editor": { - "language": "r" + "language": "r", + "editOnDblClick": false } } ] http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/markdown/src/main/resources/interpreter-setting.json ---------------------------------------------------------------------- diff --git a/markdown/src/main/resources/interpreter-setting.json b/markdown/src/main/resources/interpreter-setting.json index 8673ef9..fed93a2 100644 --- a/markdown/src/main/resources/interpreter-setting.json +++ b/markdown/src/main/resources/interpreter-setting.json @@ -12,7 +12,8 @@ } }, "editor": { - "language": "markdown" + "language": "markdown", + "editOnDblClick": true } } ] http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/pig/src/main/resources/interpreter-setting.json ---------------------------------------------------------------------- diff --git a/pig/src/main/resources/interpreter-setting.json b/pig/src/main/resources/interpreter-setting.json index 27918ed..583a126 100644 --- a/pig/src/main/resources/interpreter-setting.json +++ b/pig/src/main/resources/interpreter-setting.json @@ -18,7 +18,8 @@ } }, "editor": { - "language": "pig" + "language": "pig", + "editOnDblClick": false } }, { @@ -40,7 +41,8 @@ } }, "editor": { - "language": "pig" + "language": "pig", + "editOnDblClick": false } } ] http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/python/src/main/resources/interpreter-setting.json ---------------------------------------------------------------------- diff --git a/python/src/main/resources/interpreter-setting.json b/python/src/main/resources/interpreter-setting.json index d3df586..85f57f8 100644 --- a/python/src/main/resources/interpreter-setting.json +++ b/python/src/main/resources/interpreter-setting.json @@ -18,13 +18,19 @@ } }, "editor": { - "language": "python" + "language": "python", + "editOnDblClick": false } }, { "group": "python", "name": "sql", "className": "org.apache.zeppelin.python.PythonInterpreterPandasSql", - "properties": { } + "properties": { + }, + "editor":{ + "language": "sql", + "editOnDblClick": false + } } ] http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/shell/src/main/resources/interpreter-setting.json ---------------------------------------------------------------------- diff --git a/shell/src/main/resources/interpreter-setting.json b/shell/src/main/resources/interpreter-setting.json index d1996fa..c12b545 100644 --- a/shell/src/main/resources/interpreter-setting.json +++ b/shell/src/main/resources/interpreter-setting.json @@ -30,7 +30,8 @@ } }, "editor": { - "language": "sh" + "language": "sh", + "editOnDblClick": false } } ] http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/spark/src/main/resources/interpreter-setting.json ---------------------------------------------------------------------- diff --git a/spark/src/main/resources/interpreter-setting.json b/spark/src/main/resources/interpreter-setting.json index 55d25bd..2b78d16 100644 --- a/spark/src/main/resources/interpreter-setting.json +++ b/spark/src/main/resources/interpreter-setting.json @@ -56,7 +56,8 @@ } }, "editor": { - "language": "scala" + "language": "scala", + "editOnDblClick": false } }, { @@ -90,7 +91,8 @@ } }, "editor": { - "language": "sql" + "language": "sql", + "editOnDblClick": false } }, { @@ -112,7 +114,8 @@ } }, "editor": { - "language": "scala" + "language": "scala", + "editOnDblClick": false } }, { @@ -128,7 +131,8 @@ } }, "editor": { - "language": "python" + "language": "python", + "editOnDblClick": false } } ] http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/zeppelin-server/src/test/java/org/apache/zeppelin/integration/ParagraphActionsIT.java ---------------------------------------------------------------------- diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/integration/ParagraphActionsIT.java b/zeppelin-server/src/test/java/org/apache/zeppelin/integration/ParagraphActionsIT.java index 3ff6e1f..3ea63e3 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/integration/ParagraphActionsIT.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/integration/ParagraphActionsIT.java @@ -429,5 +429,51 @@ public class ParagraphActionsIT extends AbstractZeppelinIT { } } + @Test + public void testEditOnDoubleClick() throws Exception { + if (!endToEndTestEnabled()) { + return; + } + try { + createNewNote(); + Actions action = new Actions(driver); + waitForParagraph(1, "READY"); + + driver.findElement(By.xpath(getParagraphXPath(1) + "//textarea")).sendKeys(Keys.SHIFT + "5"); + driver.findElement(By.xpath(getParagraphXPath(1) + "//textarea")).sendKeys("md" + Keys.ENTER); + driver.findElement(By.xpath(getParagraphXPath(1) + "//textarea")).sendKeys(Keys.SHIFT + "3"); + driver.findElement(By.xpath(getParagraphXPath(1) + "//textarea")).sendKeys(" abc"); + + runParagraph(1); + waitForParagraph(1, "FINISHED"); + + collector.checkThat("Markdown editor is hidden after run ", + driver.findElement(By.xpath(getParagraphXPath(1) + "//div[contains(@ng-show, 'paragraph.config.editorHide')]")).isDisplayed(), + CoreMatchers.equalTo(false)); + + collector.checkThat("Markdown editor is shown after run ", + driver.findElement(By.xpath(getParagraphXPath(1) + "//div[contains(@ng-show, 'paragraph.config.tableHide')]")).isDisplayed(), + CoreMatchers.equalTo(true)); + + // to check if editOnDblClick field is fetched correctly after refresh + driver.navigate().refresh(); + waitForParagraph(1, "FINISHED"); + + action.doubleClick(driver.findElement(By.xpath(getParagraphXPath(1)))).perform(); + ZeppelinITUtils.sleep(1000, false); + collector.checkThat("Markdown editor is shown after double click ", + driver.findElement(By.xpath(getParagraphXPath(1) + "//div[contains(@ng-show, 'paragraph.config.editorHide')]")).isDisplayed(), + CoreMatchers.equalTo(true)); + + collector.checkThat("Markdown editor is hidden after double click ", + driver.findElement(By.xpath(getParagraphXPath(1) + "//div[contains(@ng-show, 'paragraph.config.tableHide')]")).isDisplayed(), + CoreMatchers.equalTo(false)); + + deleteTestNotebook(driver); + + } catch (Exception e) { + handleException("Exception in ParagraphActionsIT while testEditOnDoubleClick ", e); + } + } } http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/zeppelin-web/src/app/notebook/notebook.controller.js ---------------------------------------------------------------------- diff --git a/zeppelin-web/src/app/notebook/notebook.controller.js b/zeppelin-web/src/app/notebook/notebook.controller.js index 6255d73..5203a1d 100644 --- a/zeppelin-web/src/app/notebook/notebook.controller.js +++ b/zeppelin-web/src/app/notebook/notebook.controller.js @@ -139,6 +139,10 @@ // register mouseevent handler for focus paragraph document.addEventListener('keydown', $scope.keyboardShortcut); + $scope.paragraphOnDoubleClick = function(paragraphId) { + $scope.$broadcast('doubleClickParagraph', paragraphId); + }; + /** Remove the note and go back tot he main page */ /** TODO(anthony): In the nearly future, go back to the main page and telle to the dude that the note have been remove */ $scope.removeNote = function(noteId) { http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/zeppelin-web/src/app/notebook/notebook.html ---------------------------------------------------------------------- diff --git a/zeppelin-web/src/app/notebook/notebook.html b/zeppelin-web/src/app/notebook/notebook.html index 4cf6508..4f775f4 100644 --- a/zeppelin-web/src/app/notebook/notebook.html +++ b/zeppelin-web/src/app/notebook/notebook.html @@ -113,7 +113,8 @@ limitations under the License. ng-include src="'app/notebook/paragraph/paragraph.html'" ng-class="{'paragraph-space box paragraph-margin': !asIframe, 'focused': paragraphFocused, 'lastEmptyParagraph': !paragraph.text && !paragraph.result}" - ng-hide="currentParagraph.config.tableHide && viewOnly"> + ng-hide="currentParagraph.config.tableHide && viewOnly" + ng-dblclick="paragraphOnDoubleClick(currentParagraph.id);"> </div> <div class="new-paragraph" ng-click="insertNew('below');" ng-hide="!$last || viewOnly || asIframe "> <h4 class="plus-sign">+</h4> http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js ---------------------------------------------------------------------- diff --git a/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js b/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js index deab258..8fa1876 100644 --- a/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js +++ b/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js @@ -41,8 +41,9 @@ $scope.paragraph = null; $scope.originalText = ''; $scope.editor = null; - $scope.magic = null; + var editorSetting = {}; + var pastePercentSign = false; var paragraphScope = $rootScope.$new(true, $rootScope); // to keep backward compatibility @@ -300,6 +301,10 @@ data, $scope.paragraph.config, $scope.paragraph.settings.params); $scope.originalText = angular.copy(data); $scope.dirtyText = undefined; + + if (editorSetting.editOnDblClick) { + closeEditorAndOpenTable(); + } }; $scope.saveParagraph = function() { @@ -414,6 +419,23 @@ commitParagraph($scope.paragraph.title, $scope.paragraph.text, newConfig, newParams); }; + var openEditorAndCloseTable = function() { + manageEditorAndTableState(false, true); + }; + + var closeEditorAndOpenTable = function() { + manageEditorAndTableState(true, false); + }; + + var manageEditorAndTableState = function(showEditor, showTable) { + var newParams = angular.copy($scope.paragraph.settings.params); + var newConfig = angular.copy($scope.paragraph.config); + newConfig.editorHide = showEditor; + newConfig.tableHide = showTable; + + commitParagraph($scope.paragraph.title, $scope.paragraph.text, newConfig, newParams); + }; + $scope.showTitle = function() { var newParams = angular.copy($scope.paragraph.settings.params); var newConfig = angular.copy($scope.paragraph.config); @@ -626,6 +648,12 @@ $scope.handleFocus(false); }); + $scope.editor.on('paste', function(e) { + if (e.text.startsWith('%')) { + pastePercentSign = true; + } + }); + $scope.editor.getSession().on('change', function(e, editSession) { autoAdjustEditorHeight(_editor.container.id); }); @@ -705,7 +733,7 @@ } }; - var getAndSetEditorSetting = function(session, interpreterName) { + var getEditorSetting = function(interpreterName) { var deferred = $q.defer(); websocketMsgSrv.getEditorSetting($scope.paragraph.id, interpreterName); $timeout( @@ -715,42 +743,51 @@ } } ), 1000); - deferred.promise.then(function(editorSetting) { - if (!_.isEmpty(editorSetting.editor)) { - var mode = 'ace/mode/' + editorSetting.editor.language; - $scope.paragraph.config.editorMode = mode; - session.setMode(mode); - } - }); + return deferred.promise; + }; + + var setEditorLanguage = function(session, language) { + var mode = 'ace/mode/'; + mode += language; + $scope.paragraph.config.editorMode = mode; + session.setMode(mode); }; var setParagraphMode = function(session, paragraphText, pos) { // Evaluate the mode only if the the position is undefined // or the first 30 characters of the paragraph have been modified // or cursor position is at beginning of second line.(in case user hit enter after typing %magic) - if ((typeof pos === 'undefined') || (pos.row === 0 && pos.column < 30) || (pos.row === 1 && pos.column === 0)) { + if ((typeof pos === 'undefined') || (pos.row === 0 && pos.column < 30) || + (pos.row === 1 && pos.column === 0) || pastePercentSign || $scope.paragraphFocused) { // If paragraph loading, use config value if exists if ((typeof pos === 'undefined') && $scope.paragraph.config.editorMode) { session.setMode($scope.paragraph.config.editorMode); } else { - var magic; - // set editor mode to default interpreter syntax if paragraph text doesn't start with '%' - // TODO(mina): dig into the cause what makes interpreterBindings has no element - if (!paragraphText.startsWith('%') && ((typeof pos !== 'undefined') && pos.row === 0 && pos.column === 1) || - (typeof pos === 'undefined') && $scope.$parent.interpreterBindings.length !== 0) { - magic = $scope.$parent.interpreterBindings[0].name; - getAndSetEditorSetting(session, magic); - } else { - var replNameRegexp = /%(.+?)\s/g; - var match = replNameRegexp.exec(paragraphText); - if (match && $scope.magic !== match[1]) { - magic = match[1].trim(); - $scope.magic = magic; - getAndSetEditorSetting(session, magic); - } + var magic = getInterpreterName(paragraphText); + if (editorSetting.magic !== magic) { + editorSetting.magic = magic; + getEditorSetting(magic) + .then(function(setting) { + setEditorLanguage(session, setting.editor.language); + _.merge(editorSetting, setting.editor); + }); } } } + pastePercentSign = false; + }; + + var getInterpreterName = function(paragraphText) { + var intpNameRegexp = /%(.+?)\s/g; + var match = intpNameRegexp.exec(paragraphText); + if (match) { + return match[1].trim(); + // get default interpreter name if paragraph text doesn't start with '%' + // TODO(mina): dig into the cause what makes interpreterBindings to have no element + } else if ($scope.$parent.interpreterBindings.length !== 0) { + return $scope.$parent.interpreterBindings[0].name; + } + return ''; }; var autoAdjustEditorHeight = function(id) { @@ -2459,6 +2496,23 @@ } }); + $scope.$on('doubleClickParagraph', function(event, paragraphId) { + if ($scope.paragraph.id === paragraphId && editorSetting.editOnDblClick) { + var deferred = $q.defer(); + openEditorAndCloseTable(); + $timeout( + $scope.$on('updateParagraph', function(event, data) { + deferred.resolve(data); + } + ), 1000); + + deferred.promise.then(function(data) { + $scope.editor.focus(); + $scope.goToEnd(); + }); + } + }); + $scope.$on('runParagraph', function(event) { $scope.runParagraph($scope.editor.getValue()); }); http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/zeppelin-web/src/app/notebook/paragraph/paragraph.html ---------------------------------------------------------------------- diff --git a/zeppelin-web/src/app/notebook/paragraph/paragraph.html b/zeppelin-web/src/app/notebook/paragraph/paragraph.html index de102e8..ba06aea 100644 --- a/zeppelin-web/src/app/notebook/paragraph/paragraph.html +++ b/zeppelin-web/src/app/notebook/paragraph/paragraph.html @@ -67,8 +67,7 @@ limitations under the License. class="executionTime" ng-bind-html="getExecutionTime()"> </div> <div ng-if = "paragraph.status === 'RUNNING'" class = "paragraphFooterElapsed"> - <div - id="{{paragraph.id}}_elapsedTime" + <div id="{{paragraph.id}}_elapsedTime" class="elapsedTime" ng-bind-html="getElapsedTime()"> </div> </div> http://git-wip-us.apache.org/repos/asf/zeppelin/blob/60089f0f/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java ---------------------------------------------------------------------- diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java index 19081c9..63e6bee 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java @@ -127,6 +127,10 @@ public class InterpreterFactory implements InterpreterGroupFactory { private Interpreter devInterpreter; + private static final Map<String, Object> DEFAULT_EDITOR = ImmutableMap.of( + "language", (Object) "text", + "editOnDblClick", false); + public InterpreterFactory(ZeppelinConfiguration conf, AngularObjectRegistryListener angularObjectRegistryListener, RemoteInterpreterProcessListener remoteInterpreterProcessListener, @@ -429,11 +433,15 @@ public class InterpreterFactory implements InterpreterGroupFactory { String className) { List<InterpreterInfo> intpInfos = intpSetting.getInterpreterInfos(); for (InterpreterInfo intpInfo : intpInfos) { + if (className.equals(intpInfo.getClassName())) { + if (intpInfo.getEditor() == null) { + break; + } return intpInfo.getEditor(); } } - return ImmutableMap.of("language", (Object) "text"); + return DEFAULT_EDITOR; } private void loadInterpreterDependencies(final InterpreterSetting setting) { @@ -1349,9 +1357,7 @@ public class InterpreterFactory implements InterpreterGroupFactory { public Map<String, Object> getEditorSetting(String user, String noteId, String replName) { Interpreter intp = getInterpreter(user, noteId, replName); - Map<String, Object> editor = Maps.newHashMap( - ImmutableMap.<String, Object>builder() - .put("language", "text").build()); + Map<String, Object> editor = DEFAULT_EDITOR; String defaultSettingName = getDefaultInterpreterSetting(noteId).getName(); String group = StringUtils.EMPTY; try { @@ -1372,7 +1378,7 @@ public class InterpreterFactory implements InterpreterGroupFactory { } } } catch (NullPointerException e) { - logger.warn("Couldn't get interpreter editor language"); + logger.warn("Couldn't get interpreter editor setting"); } return editor; }
