You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zeppelin.apache.org by mo...@apache.org on 2015/11/24 18:51:46 UTC
incubator-zeppelin git commit: ZEPPELIN-371 : Import a notebook
Repository: incubator-zeppelin
Updated Branches:
refs/heads/master f162615fb -> fa5057cfd
ZEPPELIN-371 : Import a notebook
Import a notebook by either an external URL or uploading a valid JSON.
<img width="429" alt="screen shot 2015-10-28 at 4 53 58 pm" src="https://cloud.githubusercontent.com/assets/674497/10787159/c15c0dd6-7d94-11e5-9617-29d2361d046b.png">
<img width="1335" alt="screen shot 2015-10-28 at 4 56 30 pm" src="https://cloud.githubusercontent.com/assets/674497/10787208/046af056-7d95-11e5-99a5-3387fee393ef.png">
<img width="1171" alt="screen shot 2015-10-28 at 4 56 55 pm" src="https://cloud.githubusercontent.com/assets/674497/10787209/046e05fc-7d95-11e5-813d-ec3856a5c207.png">
<img width="1440" alt="screen shot 2015-10-28 at 4 55 29 pm" src="https://cloud.githubusercontent.com/assets/674497/10787158/c15be87e-7d94-11e5-9cde-39c0008a53bb.png">
Author: Prabhjyot Singh <pr...@gmail.com>
Closes #374 from prabhjyotsingh/ZEPPELIN-371 and squashes the following commits:
35e1e02 [Prabhjyot Singh] review changes; uniform naming: renaming IMPORT_NOTEBOOK to IMPORT_NOTE
246ae8b [Prabhjyot Singh] Fixing test case
3b8816f [Prabhjyot Singh] Import a notebook as JSON file or external URL
Project: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/commit/fa5057cf
Tree: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/tree/fa5057cf
Diff: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/diff/fa5057cf
Branch: refs/heads/master
Commit: fa5057cfd084ed36093fe032faad7f59ff22c28e
Parents: f162615
Author: Prabhjyot Singh <pr...@gmail.com>
Authored: Tue Nov 24 11:28:33 2015 +0530
Committer: Lee moon soo <mo...@apache.org>
Committed: Wed Nov 25 02:52:25 2015 +0900
----------------------------------------------------------------------
.../org/apache/zeppelin/socket/Message.java | 2 +
.../apache/zeppelin/socket/NotebookServer.java | 69 +++-
.../java/org/apache/zeppelin/ZeppelinIT.java | 2 +-
.../zeppelin/socket/NotebookServerTest.java | 21 +
zeppelin-web/src/app/home/home.css | 382 ++++++++++++++++++-
zeppelin-web/src/app/home/home.html | 2 +
.../noteName-import/note-import-dialog.html | 76 ++++
.../notenameImport.controller.js | 110 ++++++
.../websocketEvents/websocketMsg.service.js | 9 +
zeppelin-web/src/index.html | 4 +
10 files changed, 667 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/fa5057cf/zeppelin-server/src/main/java/org/apache/zeppelin/socket/Message.java
----------------------------------------------------------------------
diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/Message.java b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/Message.java
index c51cfe3..7a1c749 100644
--- a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/Message.java
+++ b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/Message.java
@@ -55,6 +55,8 @@ public class Message {
CLONE_NOTE, // [c-s] clone new notebook
// @param id id of note to clone
// @param name name fpor the cloned note
+ IMPORT_NOTE, // [c-s] import notebook
+ // @param object notebook
NOTE_UPDATE,
RUN_PARAGRAPH, // [c-s] run paragraph
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/fa5057cf/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java
----------------------------------------------------------------------
diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java
index 654d782..114582f 100644
--- a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java
+++ b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java
@@ -16,20 +16,17 @@
*/
package org.apache.zeppelin.socket;
import java.io.IOException;
-import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import javax.servlet.http.HttpServletRequest;
+
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.interpreter.InterpreterResult;
import org.apache.zeppelin.interpreter.InterpreterSetting;
import org.apache.zeppelin.notebook.JobListenerFactory;
@@ -119,6 +116,9 @@ public class NotebookServer extends WebSocketServlet implements
case CLONE_NOTE:
cloneNote(conn, notebook, messagereceived);
break;
+ case IMPORT_NOTE:
+ importNote(conn, notebook, messagereceived);
+ break;
case COMMIT_PARAGRAPH:
updateParagraph(conn, notebook, messagereceived);
break;
@@ -171,7 +171,7 @@ public class NotebookServer extends WebSocketServlet implements
}
}
- private Message deserializeMessage(String msg) {
+ protected Message deserializeMessage(String msg) {
return gson.fromJson(msg, Message.class);
}
@@ -467,6 +467,61 @@ public class NotebookServer extends WebSocketServlet implements
broadcastNoteList();
}
+ protected Note importNote(NotebookSocket conn, Notebook notebook, Message fromMessage)
+ throws IOException {
+
+ Note note = notebook.createNote();
+ if (fromMessage != null) {
+ String noteName = (String) ((Map) fromMessage.get("notebook")).get("name");
+ if (noteName == null || noteName.isEmpty()) {
+ noteName = "Note " + note.getId();
+ }
+ note.setName(noteName);
+ ArrayList<Map> paragraphs = ((Map<String, ArrayList>) fromMessage.get("notebook"))
+ .get("paragraphs");
+ if (paragraphs.size() > 0) {
+ for (Map paragraph : paragraphs) {
+ try {
+ Paragraph p = note.addParagraph();
+ String text = (String) paragraph.get("text");
+ p.setText(text);
+ p.setTitle((String) paragraph.get("title"));
+ Map<String, Object> params = (Map<String, Object>) ((Map) paragraph
+ .get("settings")).get("params");
+ Map<String, Input> forms = (Map<String, Input>) ((Map) paragraph
+ .get("settings")).get("forms");
+ if (params != null) {
+ p.settings.setParams(params);
+ }
+ if (forms != null) {
+ p.settings.setForms(forms);
+ }
+ Map<String, Object> result = (Map) paragraph.get("result");
+ if (result != null) {
+ InterpreterResult.Code code = InterpreterResult.Code
+ .valueOf((String) result.get("code"));
+ InterpreterResult.Type type = InterpreterResult.Type
+ .valueOf((String) result.get("type"));
+ String msg = (String) result.get("msg");
+ p.setReturn(new InterpreterResult(code, type, msg), null);
+ }
+
+ Map<String, Object> config = (Map<String, Object>) paragraph
+ .get("config");
+ p.setConfig(config);
+ } catch (Exception e) {
+ LOG.error("Exception while setting parameter in paragraph", e);
+ }
+ }
+ }
+ }
+
+ note.persist();
+ broadcastNote(note);
+ broadcastNoteList();
+ return note;
+ }
+
private void removeParagraph(NotebookSocket conn, Notebook notebook,
Message fromMessage) throws IOException {
final String paragraphId = (String) fromMessage.get("id");
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/fa5057cf/zeppelin-server/src/test/java/org/apache/zeppelin/ZeppelinIT.java
----------------------------------------------------------------------
diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/ZeppelinIT.java b/zeppelin-server/src/test/java/org/apache/zeppelin/ZeppelinIT.java
index dc188f8..c1b10ce 100644
--- a/zeppelin-server/src/test/java/org/apache/zeppelin/ZeppelinIT.java
+++ b/zeppelin-server/src/test/java/org/apache/zeppelin/ZeppelinIT.java
@@ -299,7 +299,7 @@ public class ZeppelinIT {
notebookTitles.add(el.getText());
}
- WebElement createNoteLink = driver.findElement(By.xpath("//div[contains(@class, \"col-md-4\")]/div/h5/a"));
+ WebElement createNoteLink = driver.findElement(By.xpath("//div[contains(@class, \"col-md-4\")]/div/h5/a[contains(.,'Create new note')]"));
createNoteLink.click();
WebDriverWait block = new WebDriverWait(driver, 10);
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/fa5057cf/zeppelin-server/src/test/java/org/apache/zeppelin/socket/NotebookServerTest.java
----------------------------------------------------------------------
diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/socket/NotebookServerTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/socket/NotebookServerTest.java
index 5275d81..faef287 100644
--- a/zeppelin-server/src/test/java/org/apache/zeppelin/socket/NotebookServerTest.java
+++ b/zeppelin-server/src/test/java/org/apache/zeppelin/socket/NotebookServerTest.java
@@ -136,6 +136,27 @@ public class NotebookServerTest extends AbstractTestRestApi {
notebook.removeNote(note1.getId());
}
+ @Test
+ public void testImportNotebook() throws IOException {
+ String msg = "{\"op\":\"IMPORT_NOTE\",\"data\":" +
+ "{\"notebook\":{\"paragraphs\": [{\"text\": \"Test " +
+ "paragraphs import\",\"config\":{},\"settings\":{}}]," +
+ "\"name\": \"Test Zeppelin notebook import\",\"config\": " +
+ "{}}}}";
+ Message messageReceived = notebookServer.deserializeMessage(msg);
+ Note note = null;
+ try {
+ note = notebookServer.importNote(null, notebook, messageReceived);
+ } catch (NullPointerException e) {
+ //broadcastNoteList(); failed nothing to worry.
+ }
+
+ assertNotEquals(null, notebook.getNote(note.getId()));
+ assertEquals("Test Zeppelin notebook import", notebook.getNote(note.getId()).getName());
+ assertEquals("Test paragraphs import", notebook.getNote(note.getId()).getParagraphs().get(0).getText());
+ notebook.removeNote(note.getId());
+ }
+
private NotebookSocket createWebSocket() {
NotebookSocket sock = mock(NotebookSocket.class);
when(sock.getRequest()).thenReturn(createHttpServletRequest());
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/fa5057cf/zeppelin-web/src/app/home/home.css
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/app/home/home.css b/zeppelin-web/src/app/home/home.css
index 0c62279..70baee9 100644
--- a/zeppelin-web/src/app/home/home.css
+++ b/zeppelin-web/src/app/home/home.css
@@ -130,30 +130,37 @@ a.navbar-brand:hover {
.navbar-inverse .navbar-nav .open .dropdown-menu > li > a {
color: #D3D3D3;
}
+
.navbar-nav .open .dropdown-menu > .scrollbar-container > li > a {
padding: 5px 15px 5px 25px;
line-height: 20px;
}
+
.navbar-inverse .navbar-nav .open .dropdown-menu > .scrollbar-container > li > a {
color: #D3D3D3;
}
+
.navbar-inverse .navbar-nav .open .dropdown-menu > .scrollbar-container > li > a:hover,
.navbar-inverse .navbar-nav .open .dropdown-menu > .scrollbar-container > li > a:focus {
color: #fff;
background-color: transparent;
}
+
.navbar-inverse .navbar-nav .open .dropdown-menu > .scrollbar-container > .active > a,
.navbar-inverse .navbar-nav .open .dropdown-menu > .scrollbar-container > .active > a:hover,
.navbar-inverse .navbar-nav .open .dropdown-menu > .scrollbar-container > .active > a:focus {
color: #fff;
background-color: #080808;
}
- .server-status{
+
+ .server-status {
float: right;
}
+
.navbar-inverse .navbar-nav .open .dropdown-menu .divider {
background-color: #3071A9;
}
+
.navbar-inverse .navbar-collapse, .navbar-inverse .navbar-form {
border-color: #3071A9;
}
@@ -210,7 +217,7 @@ a.navbar-brand:hover {
.box-heading {
position: relative;
max-width: 100%;
- font-weight:300;
+ font-weight: 300;
white-space: nowrap;
text-overflow: ellipsis;
vertical-align: middle;
@@ -310,3 +317,374 @@ This part should be removed when new version of bootstrap handles this issue.
.btn-group > .popover + .btn {
margin-left: -1px;
}
+
+.display-inline {
+ display: inline;
+ float: left;
+}
+
+#noteImportModal .modal-body {
+ min-height: 420px;
+ overflow: hidden;
+}
+
+#noteImportModal .modal-footer {
+ min-height: 65px;
+}
+
+#noteImportModal .display-inline a {
+ background-color: #fff;
+ border: 1px solid #ddd;
+ border-radius: 5px;
+ color: #999;
+ cursor: pointer;
+ display: block;
+ float: left;
+ font-size: 98px;
+ height: 240px;
+ margin: 0 10px 16px;
+ padding-top: 60px;
+ text-align: center;
+ text-decoration: none;
+ width: 264px;
+}
+
+#noteImportModal .display-inline a:hover {
+ background-color: #eee;
+}
+
+#noteImportModal .display-inline a p {
+ font-size: 14px;
+}
+
+/* ------------------------------------------- */
+/* Slide Top
+/* ------------------------------------------- */
+.slide-top {
+ -webkit-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -moz-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -ms-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -o-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ /* easeOutQuad */
+ -webkit-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -moz-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -ms-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -o-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ /* easeOutQuad */
+}
+
+.slide-top.ng-enter {
+ transform: translateY(60px);
+ -ms-transform: translateY(60px);
+ -webkit-transform: translateY(60px);
+ transition-duration: 250ms;
+ -webkit-transition-duration: 250ms;
+ opacity: 0;
+}
+
+.slide-top.ng-enter-active {
+ transform: translateY(0);
+ -ms-transform: translateY(0);
+ -webkit-transform: translateY(0);
+ opacity: 1;
+}
+
+.slide-top.ng-leave {
+ transform: translateY(0);
+ -ms-transform: translateY(0);
+ -webkit-transform: translateY(0);
+ transition-duration: 250ms;
+ -webkit-transition-duration: 250ms;
+ opacity: 1;
+}
+
+.slide-top.ng-leave-active {
+ transform: translateY(60px);
+ -ms-transform: translateY(60px);
+ -webkit-transform: translateY(60px);
+ opacity: 0;
+}
+
+.slide-top.ng-hide-add {
+ transform: translateY(0);
+ -ms-transform: translateY(0);
+ -webkit-transform: translateY(0);
+ transition-duration: 250ms;
+ -webkit-transition-duration: 250ms;
+ opacity: 1;
+}
+
+.slide-top.ng-hide-add.ng-hide-add-active {
+ transform: translateY(60px);
+ -ms-transform: translateY(60px);
+ -webkit-transform: translateY(60px);
+ opacity: 0;
+}
+
+.slide-top.ng-hide-remove {
+ transform: translateY(60px);
+ -ms-transform: translateY(60px);
+ -webkit-transform: translateY(60px);
+ transition-duration: 250ms;
+ -webkit-transition-duration: 250ms;
+ display: block !important;
+ opacity: 0;
+}
+
+.slide-top.ng-hide-remove.ng-hide-remove-active {
+ transform: translateY(0);
+ -ms-transform: translateY(0);
+ -webkit-transform: translateY(0);
+ opacity: 1;
+}
+
+/* ------------------------------------------- */
+/* Slide Right
+/* ------------------------------------------- */
+.slide-right {
+ -webkit-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -moz-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -ms-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -o-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ /* easeOutQuad */
+ -webkit-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -moz-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -ms-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -o-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ /* easeOutQuad */
+}
+
+.slide-right.ng-enter {
+ transform: translateX(60px);
+ -ms-transform: translateX(60px);
+ -webkit-transform: translateX(60px);
+ transition-duration: 250ms;
+ -webkit-transition-duration: 250ms;
+ opacity: 0;
+}
+
+.slide-right.ng-enter-active {
+ transform: translateX(0);
+ -ms-transform: translateX(0);
+ -webkit-transform: translateX(0);
+ opacity: 1;
+}
+
+.slide-right.ng-leave {
+ transform: translateX(0);
+ -ms-transform: translateX(0);
+ -webkit-transform: translateX(0);
+ transition-duration: 250ms;
+ -webkit-transition-duration: 250ms;
+ opacity: 1;
+}
+
+.slide-right.ng-leave-active {
+ transform: translateX(60px);
+ -ms-transform: translateX(60px);
+ -webkit-transform: translateX(60px);
+ opacity: 0;
+}
+
+.slide-right.ng-hide-add {
+ transform: translateX(0);
+ -ms-transform: translateX(0);
+ -webkit-transform: translateX(0);
+ transition-duration: 250ms;
+ -webkit-transition-duration: 250ms;
+ opacity: 1;
+}
+
+.slide-right.ng-hide-add.ng-hide-add-active {
+ transform: translateX(60px);
+ -ms-transform: translateX(60px);
+ -webkit-transform: translateX(60px);
+ opacity: 0;
+}
+
+.slide-right.ng-hide-remove {
+ transform: translateX(60px);
+ -ms-transform: translateX(60px);
+ -webkit-transform: translateX(60px);
+ transition-duration: 250ms;
+ -webkit-transition-duration: 250ms;
+ display: block !important;
+ opacity: 0;
+}
+
+.slide-right.ng-hide-remove.ng-hide-remove-active {
+ transform: translateX(0);
+ -ms-transform: translateX(0);
+ -webkit-transform: translateX(0);
+ opacity: 1;
+}
+
+/* ------------------------------------------- */
+/* Slide Left
+/* ------------------------------------------- */
+.slide-left {
+ -webkit-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -moz-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -ms-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -o-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ /* easeOutQuad */
+ -webkit-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -moz-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -ms-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -o-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ /* easeOutQuad */
+}
+
+.slide-left.ng-enter {
+ transform: translateX(-60px);
+ -ms-transform: translateX(-60px);
+ -webkit-transform: translateX(-60px);
+ transition-duration: 250ms;
+ -webkit-transition-duration: 250ms;
+ opacity: 0;
+}
+
+.slide-left.ng-enter-active {
+ transform: translateX(0);
+ -ms-transform: translateX(0);
+ -webkit-transform: translateX(0);
+ opacity: 1;
+}
+
+.slide-left.ng-leave {
+ transform: translateX(0);
+ -ms-transform: translateX(0);
+ -webkit-transform: translateX(0);
+ transition-duration: 250ms;
+ -webkit-transition-duration: 250ms;
+ opacity: 1;
+}
+
+.slide-left.ng-leave-active {
+ transform: translateX(-60px);
+ -ms-transform: translateX(-60px);
+ -webkit-transform: translateX(-60px);
+ opacity: 0;
+}
+
+.slide-left.ng-hide-add {
+ transform: translateX(0);
+ -ms-transform: translateX(0);
+ -webkit-transform: translateX(0);
+ transition-duration: 250ms;
+ -webkit-transition-duration: 250ms;
+ opacity: 1;
+}
+
+.slide-left.ng-hide-add.ng-hide-add-active {
+ transform: translateX(-60px);
+ -ms-transform: translateX(-60px);
+ -webkit-transform: translateX(-60px);
+ opacity: 0;
+}
+
+.slide-left.ng-hide-remove {
+ transform: translateX(-60px);
+ -ms-transform: translateX(-60px);
+ -webkit-transform: translateX(-60px);
+ transition-duration: 250ms;
+ -webkit-transition-duration: 250ms;
+ display: block !important;
+ opacity: 0;
+}
+
+.slide-left.ng-hide-remove.ng-hide-remove-active {
+ transform: translateX(0);
+ -ms-transform: translateX(0);
+ -webkit-transform: translateX(0);
+ opacity: 1;
+}
+
+/* ------------------------------------------- */
+/* Slide Down
+/* ------------------------------------------- */
+.slide-down {
+ -webkit-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -moz-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -ms-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -o-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ /* easeOutQuad */
+ -webkit-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -moz-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -ms-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ -o-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
+ /* easeOutQuad */
+}
+
+.slide-down.ng-enter {
+ transform: translateY(-60px);
+ -ms-transform: translateY(-60px);
+ -webkit-transform: translateY(-60px);
+ transition-duration: 250ms;
+ -webkit-transition-duration: 250ms;
+ opacity: 0;
+}
+
+.slide-down.ng-enter-active {
+ transform: translateY(0);
+ -ms-transform: translateY(0);
+ -webkit-transform: translateY(0);
+ opacity: 1;
+}
+
+.slide-down.ng-leave {
+ transform: translateY(0);
+ -ms-transform: translateY(0);
+ -webkit-transform: translateY(0);
+ transition-duration: 250ms;
+ -webkit-transition-duration: 250ms;
+ opacity: 1;
+}
+
+.slide-down.ng-leave-active {
+ transform: translateY(-60px);
+ -ms-transform: translateY(-60px);
+ -webkit-transform: translateY(-60px);
+ opacity: 0;
+}
+
+.slide-down.ng-hide-add {
+ transform: translateY(0);
+ -ms-transform: translateY(0);
+ -webkit-transform: translateY(0);
+ transition-duration: 250ms;
+ -webkit-transition-duration: 250ms;
+ opacity: 1;
+}
+
+.slide-down.ng-hide-add.ng-hide-add-active {
+ transform: translateY(-60px);
+ -ms-transform: translateY(-60px);
+ -webkit-transform: translateY(-60px);
+ opacity: 0;
+}
+
+.slide-down.ng-hide-remove {
+ transform: translateY(-60px);
+ -ms-transform: translateY(-60px);
+ -webkit-transform: translateY(-60px);
+ transition-duration: 250ms;
+ -webkit-transition-duration: 250ms;
+ display: block !important;
+ opacity: 0;
+}
+
+.slide-down.ng-hide-remove.ng-hide-remove-active {
+ transform: translateY(0);
+ -ms-transform: translateY(0);
+ -webkit-transform: translateY(0);
+ opacity: 1;
+}
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/fa5057cf/zeppelin-web/src/app/home/home.html
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/app/home/home.html b/zeppelin-web/src/app/home/home.html
index cdefa69..56e6dc4 100644
--- a/zeppelin-web/src/app/home/home.html
+++ b/zeppelin-web/src/app/home/home.html
@@ -29,6 +29,8 @@ limitations under the License.
<h4>Notebook</h4>
<div>
+ <h5><a href="" data-toggle="modal" data-target="#noteImportModal" style="text-decoration: none;">
+ <i style="font-size: 15px;" class="fa fa-upload"></i> Import note</a></h5>
<h5><a href="" data-toggle="modal" data-target="#noteNameModal" style="text-decoration: none;">
<i style="font-size: 15px;" class="icon-notebook"></i> Create new note</a></h5>
<ul style="list-style-type: none;">
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/fa5057cf/zeppelin-web/src/components/noteName-import/note-import-dialog.html
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/noteName-import/note-import-dialog.html b/zeppelin-web/src/components/noteName-import/note-import-dialog.html
new file mode 100644
index 0000000..524e4d2
--- /dev/null
+++ b/zeppelin-web/src/components/noteName-import/note-import-dialog.html
@@ -0,0 +1,76 @@
+<!--
+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.
+-->
+
+ <div id="noteImportModal" class="modal fade" role="dialog"
+ tabindex='-1'>
+ <div class="modal-dialog">
+
+ <!-- Modal content-->
+ <div class="modal-content" id="NoteImportCtrl" ng-init="NoteImportInit">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal">×</button>
+ <h4 class="modal-title">Import new note</h4>
+ </div>
+ <div class="modal-body">
+
+ <div class="form-group">
+ <label for="noteImportName">Import AS</label>
+ <input placeholder="Note name" type="text" class="form-control" id="noteImportName"
+ ng-model="note.noteImportName">
+ </div>
+
+ <div class="form-group" ng-show="note.errorText">
+ <div class="alert alert-danger">{{note.errorText}}</div>
+ </div>
+
+ <div class="form-group slide-left" ng-show="note.step1">
+ <div class="display-inline">
+ <a class="fa fa-cloud-upload import-file-upload" ng-click="uploadFile()">
+ <p>Choose a JSON here</p>
+ </a>
+ </div>
+ <div style="display: none">
+ <input placeholder="Note name" type="file" class="form-control" id="noteImportFile"
+ ng-model="note.importFile" onchange="angular.element(this).scope().importFile(this)">
+ </div>
+ <div class="display-inline">
+ <a href="javascript:void(0);" ng-click="uploadURL()" class="fa fa-link">
+ <p>Add from URL</p>
+ </a>
+ </div>
+ </div>
+
+ <div class="form-group slide-right" ng-show="note.step2">
+
+ <label for="noteImportUrl">URL</label>
+ <input placeholder="Note name" type="text" class="form-control" id="noteImportUrl"
+ ng-model="note.importUrl">
+ </div>
+
+ </div>
+ <div class="modal-footer">
+ <div ng-show="note.step2">
+ <button type="button" id="importBackButton"
+ class="btn btn-default"
+ ng-click="noteimportctrl.importBack()">Back
+ </button>
+ <button type="button" id="importNoteButton"
+ class="btn btn-default"
+ ng-click="noteimportctrl.importNote()">Import Note
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/fa5057cf/zeppelin-web/src/components/noteName-import/notenameImport.controller.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/noteName-import/notenameImport.controller.js b/zeppelin-web/src/components/noteName-import/notenameImport.controller.js
new file mode 100644
index 0000000..d48179d
--- /dev/null
+++ b/zeppelin-web/src/components/noteName-import/notenameImport.controller.js
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+'use strict';
+
+angular.module('zeppelinWebApp').controller('NoteImportCtrl', function($scope, $timeout, websocketMsgSrv) {
+ var vm = this;
+ $scope.note = {};
+ $scope.note.step1 = true;
+ $scope.note.step2 = false;
+
+ vm.resetFlags = function() {
+ $scope.note = {};
+ $scope.note.step1 = true;
+ $scope.note.step2 = false;
+ angular.element('#noteImportFile').val('');
+ };
+
+ $scope.uploadFile = function() {
+ angular.element('#noteImportFile').click();
+ };
+
+ $scope.importFile = function(element) {
+ $scope.note.errorText = '';
+ $scope.note.importFile = element.files[0];
+ var file = $scope.note.importFile;
+ var reader = new FileReader();
+
+ reader.onloadend = function() {
+ vm.processImportJson(reader.result);
+ };
+
+ if (file) {
+ reader.readAsText(file);
+ }
+ };
+
+ $scope.uploadURL = function() {
+ $scope.note.errorText = '';
+ $scope.note.step1 = false;
+ $timeout(function() {
+ $scope.note.step2 = true;
+ }, 400);
+ };
+
+ vm.importBack = function() {
+ $scope.note.errorText = '';
+ $timeout(function() {
+ $scope.note.step1 = true;
+ }, 400);
+ $scope.note.step2 = false;
+ };
+
+ vm.importNote = function() {
+ $scope.note.errorText = '';
+ if ($scope.note.importUrl) {
+ jQuery.getJSON($scope.note.importUrl, function(result) {
+ vm.processImportJson(result);
+ }).fail(function() {
+ $scope.note.errorText = 'Unable to Fetch URL';
+ $scope.$apply();
+ });
+ }
+ else {
+ $scope.note.errorText = 'Enter URL';
+ $scope.$apply();
+ }
+ };
+
+ vm.processImportJson = function(result) {
+ if (typeof result !== 'object') {
+ try {
+ result = JSON.parse(result);
+ } catch (e) {
+ $scope.note.errorText = 'JSON parse exception';
+ $scope.$apply();
+ return;
+ }
+
+ }
+ if (result.paragraphs && result.paragraphs.length > 0) {
+ if (!$scope.note.noteImportName) {
+ $scope.note.noteImportName = result.name;
+ } else {
+ result.name = $scope.note.noteImportName;
+ }
+ websocketMsgSrv.importNotebook(result);
+ //angular.element('#noteImportModal').modal('hide');
+ } else {
+ $scope.note.errorText = 'Invalid JSON';
+ }
+ $scope.$apply();
+ };
+
+ $scope.$on('setNoteMenu', function(event, notes) {
+ vm.resetFlags();
+ angular.element('#noteImportModal').modal('hide');
+ });
+});
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/fa5057cf/zeppelin-web/src/components/websocketEvents/websocketMsg.service.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/websocketEvents/websocketMsg.service.js b/zeppelin-web/src/components/websocketEvents/websocketMsg.service.js
index 6022543..a10bc87 100644
--- a/zeppelin-web/src/components/websocketEvents/websocketMsg.service.js
+++ b/zeppelin-web/src/components/websocketEvents/websocketMsg.service.js
@@ -113,6 +113,15 @@ angular.module('zeppelinWebApp').service('websocketMsgSrv', function($rootScope,
});
},
+ importNotebook: function(notebook) {
+ websocketEvents.sendNewEvent({
+ op: 'IMPORT_NOTE',
+ data: {
+ notebook: notebook
+ }
+ });
+ },
+
isConnected: function(){
return websocketEvents.isConnected();
}
http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/fa5057cf/zeppelin-web/src/index.html
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/index.html b/zeppelin-web/src/index.html
index b8dd489..0d065a5 100644
--- a/zeppelin-web/src/index.html
+++ b/zeppelin-web/src/index.html
@@ -73,6 +73,9 @@ limitations under the License.
<div ng-controller="NotenameCtrl as notenamectrl">
<div id="note-modal-container" ng-include src="'components/noteName-create/note-name-dialog.html'"></div>
</div>
+ <div ng-controller="NoteImportCtrl as noteimportctrl">
+ <div id="note-import-container" ng-include src="'components/noteName-import/note-import-dialog.html'"></div>
+ </div>
<!-- build:js(.) scripts/oldieshim.js -->
<!--[if lt IE 9]>
<script src="bower_components/es5-shim/es5-shim.js"></script>
@@ -129,6 +132,7 @@ limitations under the License.
<script src="components/navbar/navbar.controller.js"></script>
<script src="components/ngescape/ngescape.directive.js"></script>
<script src="components/noteName-create/notename.controller.js"></script>
+ <script src="components/noteName-import/notenameImport.controller.js"></script>
<script src="components/popover-html-unsafe/popover-html-unsafe.directive.js"></script>
<script src="components/ngenter/ngenter.directive.js"></script>
<script src="components/dropdowninput/dropdowninput.directive.js"></script>