Repository: zeppelin Updated Branches: refs/heads/master daceee568 -> 5cdc02d36
[Zeppelin - 1152] Listing note revision history ### What is this PR for? This PR addresses ability to view the history of note revisions from the `version control` menu ### What type of PR is it? Improvement ### Todos * [x] - backend changes * [x] - tests * [x] - propagation to frontend * [x] - rendering list ### What is the Jira issue? [Zeppelin - 1152](https://issues.apache.org/jira/browse/ZEPPELIN-1152) ### How should this be tested? 1. Select Git notebook storage layer as primary (e.g. in `conf/zeppelin-env.sh` add ``` export ZEPPELIN_NOTEBOOK_STORAGE="org.apache.zeppelin.notebook.repo.GitNotebookRepo" ``` 2. Select any note in Zeppelin and `commit` it in `version control` menu 3. The list with new commit should be shown in the same menu ### Screenshots (if appropriate) <img width="782" alt="screen shot 2016-07-21 at 11 35 21 am" src="https://cloud.githubusercontent.com/assets/1642088/17009639/c8bcbd58-4f37-11e6-92cd-88147b7419e6.png"> ### Questions: * Does the licenses files need update? No * Is there breaking changes for older versions? No * Does this needs documentation? No Author: Khalid Huseynov <[email protected]> Author: Khalid Huseynov <[email protected]> Author: Damien CORNEAU <[email protected]> Closes #1160 from khalidhuseynov/front/list-revision-history and squashes the following commits: 924a6c5 [Khalid Huseynov] address @corneadoug comments 614ed61 [Khalid Huseynov] date: smaller font and spacing f676b74 [Khalid Huseynov] Merge branch 'master' into front/list-revision-history bd068fd [Khalid Huseynov] add css class with smaller font for revision date 0445b42 [Khalid Huseynov] move date to right, add time 4607c03 [Khalid Huseynov] fix css e6bafde [Khalid Huseynov] change time format 2090d60 [Khalid Huseynov] mock listRevisionHistory 1d20aeb [Khalid Huseynov] fix jshint checkstyle ee7b94f [Damien CORNEAU] Reverse revisions order to have the latest first 9523b48 [Damien CORNEAU] Add dropdown of revisions 660139b [Damien CORNEAU] fix the jscs error bcf6cf1 [Khalid Huseynov] return list on successful commit 18d430a [Khalid Huseynov] add initial listing b4c69df [Khalid Huseynov] add test: revision history, multiple notes d8f4282 [Khalid Huseynov] add new note resource for tests with multiple notes a7e8fd8 [Khalid Huseynov] initial impl Project: http://git-wip-us.apache.org/repos/asf/zeppelin/repo Commit: http://git-wip-us.apache.org/repos/asf/zeppelin/commit/5cdc02d3 Tree: http://git-wip-us.apache.org/repos/asf/zeppelin/tree/5cdc02d3 Diff: http://git-wip-us.apache.org/repos/asf/zeppelin/diff/5cdc02d3 Branch: refs/heads/master Commit: 5cdc02d3651fc8f5b7f9aa81f1d617007932b666 Parents: daceee5 Author: Khalid Huseynov <[email protected]> Authored: Thu Jul 21 11:32:01 2016 +0900 Committer: Alexander Bezzubov <[email protected]> Committed: Thu Jul 21 20:22:30 2016 +0900 ---------------------------------------------------------------------- .../apache/zeppelin/socket/NotebookServer.java | 21 ++++- .../src/app/notebook/notebook-actionBar.html | 83 +++++++++++++------ .../src/app/notebook/notebook.controller.js | 15 ++++ zeppelin-web/src/app/notebook/notebook.css | 42 ++++++++++ .../websocketEvents/websocketEvents.factory.js | 2 + .../websocketEvents/websocketMsg.service.js | 9 ++ zeppelin-web/test/spec/controllers/notebook.js | 3 +- .../org/apache/zeppelin/notebook/Notebook.java | 11 ++- .../notebook/repo/NotebookRepoSync.java | 10 ++- .../zeppelin/notebook/socket/Message.java | 3 + .../notebook/repo/GitNotebookRepoTest.java | 55 ++++++++++++- .../src/test/resources/2A94M5J2Z/note.json | 87 ++++++++++++++++++++ 12 files changed, 303 insertions(+), 38 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5cdc02d3/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 1859ba0..0f8ce70 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 @@ -45,6 +45,7 @@ import org.apache.zeppelin.interpreter.InterpreterResult; import org.apache.zeppelin.interpreter.InterpreterSetting; import org.apache.zeppelin.interpreter.remote.RemoteInterpreterProcessListener; import org.apache.zeppelin.notebook.*; +import org.apache.zeppelin.notebook.repo.NotebookRepo; import org.apache.zeppelin.notebook.repo.NotebookRepo.Revision; import org.apache.zeppelin.notebook.socket.Message; import org.apache.zeppelin.notebook.socket.Message.OP; @@ -221,6 +222,9 @@ public class NotebookServer extends WebSocketServlet implements case CHECKPOINT_NOTEBOOK: checkpointNotebook(conn, notebook, messagereceived); break; + case LIST_REVISION_HISTORY: + listRevisionHistory(conn, notebook, messagereceived); + break; case NOTE_REVISION: getNoteRevision(conn, notebook, messagereceived); break; @@ -1130,7 +1134,22 @@ public class NotebookServer extends WebSocketServlet implements String noteId = (String) fromMessage.get("noteId"); String commitMessage = (String) fromMessage.get("commitMessage"); AuthenticationInfo subject = new AuthenticationInfo(fromMessage.principal); - notebook.checkpointNote(noteId, commitMessage, subject); + Revision revision = notebook.checkpointNote(noteId, commitMessage, subject); + if (revision != null) { + List<NotebookRepo.Revision> revisions = notebook.listRevisionHistory(noteId, subject); + conn.send(serializeMessage(new Message(OP.LIST_REVISION_HISTORY) + .put("revisionList", revisions))); + } + } + + private void listRevisionHistory(NotebookSocket conn, Notebook notebook, + Message fromMessage) throws IOException { + String noteId = (String) fromMessage.get("noteId"); + AuthenticationInfo subject = new AuthenticationInfo(fromMessage.principal); + List<NotebookRepo.Revision> revisions = notebook.listRevisionHistory(noteId, subject); + + conn.send(serializeMessage(new Message(OP.LIST_REVISION_HISTORY) + .put("revisionList", revisions))); } private void getNoteRevision(NotebookSocket conn, Notebook notebook, Message fromMessage) http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5cdc02d3/zeppelin-web/src/app/notebook/notebook-actionBar.html ---------------------------------------------------------------------- diff --git a/zeppelin-web/src/app/notebook/notebook-actionBar.html b/zeppelin-web/src/app/notebook/notebook-actionBar.html index 170d56d..cf13d50 100644 --- a/zeppelin-web/src/app/notebook/notebook-actionBar.html +++ b/zeppelin-web/src/app/notebook/notebook-actionBar.html @@ -64,34 +64,63 @@ limitations under the License. tooltip-placement="bottom" tooltip="Export the notebook"> <i class="fa fa-download"></i> </button> - <button type="button" - class="btn btn-default btn-xs dropdown-toggle" - ng-hide="viewOnly" - data-toggle="dropdown" - tooltip-placement="bottom" tooltip="Version control"> - <i class="fa fa-file-code-o"></i> - </button> - <ul class="dropdown-menu" role="menu" style="width:250px"> - <li> - <div class="commit-container"> - <div> - <input type="text" - dropdown-input - placeholder="commit message" - id="note.checkpoint.message" - style="width: 145px;" - ng-model="note.checkpoint.message"/> - <button type="button" - class="btn btn-default btn-xs" - ng-hide="viewOnly" - ng-click="checkpointNotebook(note.checkpoint.message)" - style="margin-left: 4px;" - tooltip-placement="bottom" tooltip="Commit the notebook">Commit - </button> + </span> + + <span class="labelBtn btn-group" role="group"> + <div class="btn-group" role="group"> + <button type="button" + class="btn btn-default btn-xs dropdown-toggle" + id="versionControlDropdown" + ng-hide="viewOnly" + data-toggle="dropdown" + tooltip-placement="bottom" tooltip="Version control"> + <i class="fa fa-file-code-o"></i> + </button> + <ul class="dropdown-menu" style="width:250px" + aria-labelledby="versionControlDropdown"> + <li> + <div class="commit-container"> + <div> + <input type="text" + dropdown-input + placeholder="commit message" + id="note.checkpoint.message" + style="width: 145px;" + ng-model="note.checkpoint.message"/> + <button type="button" + class="btn btn-default btn-xs" + ng-hide="viewOnly" + ng-click="checkpointNotebook(note.checkpoint.message)" + style="margin-left: 4px;" + tooltip-placement="bottom" tooltip="Commit the notebook">Commit + </button> + </div> </div> - </div> - </li> - </ul> + </li> + </ul> + </div> + <div class="btn-group" role="group"> + <button type="button" class="btn btn-default btn-xs revisionName"> + Head + </button> + <button type="button" ng-if="noteRevisions.length > 0" + class="btn btn-default dropdown-toggle caretSeparator" + data-toggle="dropdown" id="revisionsDropdown"> + <span class="caret"></span> + </button> + <ul class="dropdown-menu pull-right" aria-labelledby="revisionsDropdown"> + <li ng-repeat="revision in noteRevisions | orderBy:'time':true" class="revision"> + <a style="cursor:pointer"> + <span style="display: block;"> + <strong>{{revision.message}}</strong> + </span> + <span class="revisionDate"> + <em>{{moment.unix(revision.time).format('MMMM Do YYYY, h:mm a')}}</em> + </span> + </a> + </li> + </ul> + </div> </span> <!-- put the delete action by itself for your protection --> http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5cdc02d3/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 81b9c32..dc59f50 100644 --- a/zeppelin-web/src/app/notebook/notebook.controller.js +++ b/zeppelin-web/src/app/notebook/notebook.controller.js @@ -17,6 +17,7 @@ angular.module('zeppelinWebApp').controller('NotebookCtrl', function($scope, $ro $rootScope, $http, websocketMsgSrv, baseUrlSrv, $timeout, saveAsService) { $scope.note = null; + $scope.moment = moment; $scope.showEditor = false; $scope.editorToggled = false; $scope.tableToggled = false; @@ -52,6 +53,14 @@ angular.module('zeppelinWebApp').controller('NotebookCtrl', function($scope, $ro var previousSelectedListWriters = []; var searchText = []; $scope.role = ''; + $scope.noteRevisions = []; + + $scope.$on('setConnectedStatus', function(event, param) { + if (connectedOnce && param) { + initNotebook(); + } + connectedOnce = true; + }); $scope.getCronOptionNameFromValue = function(value) { if (!value) { @@ -69,6 +78,7 @@ angular.module('zeppelinWebApp').controller('NotebookCtrl', function($scope, $ro /** Init the new controller */ var initNotebook = function() { websocketMsgSrv.getNotebook($routeParams.noteId); + websocketMsgSrv.listRevisionHistory($routeParams.noteId); var currentRoute = $route.current; if (currentRoute) { @@ -173,6 +183,11 @@ angular.module('zeppelinWebApp').controller('NotebookCtrl', function($scope, $ro document.getElementById('note.checkpoint.message').value = ''; }; + $scope.$on('listRevisionHistory', function(event, data) { + console.log('We got the revisions %o', data); + $scope.noteRevisions = data.revisionList; + }); + // receive certain revision of note $scope.$on('noteRevision', function(event, data) { console.log('received note revision %o', data); http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5cdc02d3/zeppelin-web/src/app/notebook/notebook.css ---------------------------------------------------------------------- diff --git a/zeppelin-web/src/app/notebook/notebook.css b/zeppelin-web/src/app/notebook/notebook.css index 59f7561..ed45c67 100644 --- a/zeppelin-web/src/app/notebook/notebook.css +++ b/zeppelin-web/src/app/notebook/notebook.css @@ -16,6 +16,48 @@ padding-top: 36px; } +.revision { + max-width: 250px; + margin-bottom: 0 !important; +} + +.revision a { + padding: 2px 10px !important; +} + +.revision a span { + width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.revisionName { + cursor: default; + padding: 1px 10px !important; + max-width: 150px; +} + +.revisionDate { + font-size: 8px; + color: DarkGrey; + display: block; +} + +.revisionName:hover, +.revisionName:focus, +.revisionName:active { + background: transparent; + border-color: #ccc; +} + +.caretSeparator { + height: 22px; + line-height: 9px; + width: 16px; + padding-left: 3px !important; +} + .paragraph-col { margin: 0; padding: 0; http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5cdc02d3/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js ---------------------------------------------------------------------- diff --git a/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js b/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js index 6c9eeee..7657137 100644 --- a/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js +++ b/zeppelin-web/src/components/websocketEvents/websocketEvents.factory.js @@ -109,6 +109,8 @@ angular.module('zeppelinWebApp').factory('websocketEvents', $rootScope.$broadcast('appLoad', data); } else if (op === 'APP_STATUS_CHANGE') { $rootScope.$broadcast('appStatusChange', data); + } else if (op === 'LIST_REVISION_HISTORY') { + $rootScope.$broadcast('listRevisionHistory', data); } else if (op === 'NOTE_REVISION') { $rootScope.$broadcast('noteRevision', data); } http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5cdc02d3/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 9a82c9b..a4f7802 100644 --- a/zeppelin-web/src/components/websocketEvents/websocketMsg.service.js +++ b/zeppelin-web/src/components/websocketEvents/websocketMsg.service.js @@ -161,6 +161,15 @@ angular.module('zeppelinWebApp').service('websocketMsgSrv', function($rootScope, }); }, + listRevisionHistory: function(noteId) { + websocketEvents.sendNewEvent({ + op: 'LIST_REVISION_HISTORY', + data: { + noteId: noteId + } + }); + }, + getNoteRevision: function(noteId, revisionId) { websocketEvents.sendNewEvent({ op: 'NOTE_REVISION', http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5cdc02d3/zeppelin-web/test/spec/controllers/notebook.js ---------------------------------------------------------------------- diff --git a/zeppelin-web/test/spec/controllers/notebook.js b/zeppelin-web/test/spec/controllers/notebook.js index 77ddfff..d9b35b1 100644 --- a/zeppelin-web/test/spec/controllers/notebook.js +++ b/zeppelin-web/test/spec/controllers/notebook.js @@ -6,7 +6,8 @@ describe('Controller: NotebookCtrl', function() { var scope; var websocketMsgSrvMock = { - getNotebook: function() {} + getNotebook: function() {}, + listRevisionHistory: function() {} }; var baseUrlSrvMock = { http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5cdc02d3/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java ---------------------------------------------------------------------- diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java index 9937d61..3620464 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java @@ -353,9 +353,14 @@ public class Notebook implements NoteEventListener { } } - public void checkpointNote(String noteId, String checkpointMessage, AuthenticationInfo subject) - throws IOException { - notebookRepo.checkpoint(noteId, checkpointMessage, subject); + public Revision checkpointNote(String noteId, String checkpointMessage, + AuthenticationInfo subject) throws IOException { + return notebookRepo.checkpoint(noteId, checkpointMessage, subject); + } + + public List<NotebookRepo.Revision> listRevisionHistory(String noteId, + AuthenticationInfo subject) { + return notebookRepo.revisionHistory(noteId, subject); } public Note getNoteRevision(String noteId, Revision revision, AuthenticationInfo subject) http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5cdc02d3/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/NotebookRepoSync.java ---------------------------------------------------------------------- diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/NotebookRepoSync.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/NotebookRepoSync.java index 4e735e8..6c499c6 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/NotebookRepoSync.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/NotebookRepoSync.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -366,7 +367,12 @@ public class NotebookRepoSync implements NotebookRepo { @Override public List<Revision> revisionHistory(String noteId, AuthenticationInfo subject) { - // Auto-generated method stub - return null; + List<Revision> revisions = Collections.emptyList(); + try { + revisions = getRepo(0).revisionHistory(noteId, subject); + } catch (IOException e) { + LOG.error("Failed to list revision history", e); + } + return revisions; } } http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5cdc02d3/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java ---------------------------------------------------------------------- diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java index c0baf40..e2f5fe9 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/socket/Message.java @@ -114,6 +114,9 @@ public class Message { CHECKPOINT_NOTEBOOK, // [c-s] checkpoint notebook to storage repository // @param noteId // @param checkpointName + + LIST_REVISION_HISTORY, // [c-s] list revision history of the notebook + // @param noteId NOTE_REVISION, // [c-s] get certain revision of note // @param noteId // @param revisionId http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5cdc02d3/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/GitNotebookRepoTest.java ---------------------------------------------------------------------- diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/GitNotebookRepoTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/GitNotebookRepoTest.java index 8e787a2..b1d4b38 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/GitNotebookRepoTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/GitNotebookRepoTest.java @@ -46,6 +46,7 @@ import com.google.common.base.Joiner; public class GitNotebookRepoTest { private static final String TEST_NOTE_ID = "2A94M5J1Z"; + private static final String TEST_NOTE_ID2 = "2A94M5J2Z"; private File zeppelinDir; private String notebooksDir; @@ -54,7 +55,7 @@ public class GitNotebookRepoTest { @Before public void setUp() throws Exception { - String zpath = System.getProperty("java.io.tmpdir")+"/ZeppelinTest_"+System.currentTimeMillis(); + String zpath = System.getProperty("java.io.tmpdir") + "/ZeppelinTest_" + System.currentTimeMillis(); zeppelinDir = new File(zpath); zeppelinDir.mkdirs(); new File(zeppelinDir, "conf").mkdirs(); @@ -64,8 +65,11 @@ public class GitNotebookRepoTest { notebookDir.mkdirs(); String testNoteDir = Joiner.on(File.separator).join(notebooksDir, TEST_NOTE_ID); + String testNoteDir2 = Joiner.on(File.separator).join(notebooksDir, TEST_NOTE_ID2); FileUtils.copyDirectory(new File(Joiner.on(File.separator).join("src", "test", "resources", TEST_NOTE_ID)), - new File(testNoteDir) + new File(testNoteDir)); + FileUtils.copyDirectory(new File(Joiner.on(File.separator).join("src", "test", "resources", TEST_NOTE_ID2)), + new File(testNoteDir2) ); System.setProperty(ConfVars.ZEPPELIN_HOME.getVarName(), zeppelinDir.getAbsolutePath()); @@ -106,7 +110,7 @@ public class GitNotebookRepoTest { } @Test - public void showNotebookHistory() throws GitAPIException, IOException { + public void showNotebookHistoryEmptyTest() throws GitAPIException, IOException { //given notebookRepo = new GitNotebookRepo(conf); assertThat(notebookRepo.list(null)).isNotEmpty(); @@ -120,7 +124,50 @@ public class GitNotebookRepoTest { } @Test - public void addCheckpoint() throws IOException { + public void showNotebookHistoryMultipleNotesTest() throws IOException { + //initial checks + notebookRepo = new GitNotebookRepo(conf); + assertThat(notebookRepo.list(null)).isNotEmpty(); + assertThat(containsNote(notebookRepo.list(null), TEST_NOTE_ID)).isTrue(); + assertThat(containsNote(notebookRepo.list(null), TEST_NOTE_ID2)).isTrue(); + assertThat(notebookRepo.revisionHistory(TEST_NOTE_ID, null)).isEmpty(); + assertThat(notebookRepo.revisionHistory(TEST_NOTE_ID2, null)).isEmpty(); + + //add commit to both notes + notebookRepo.checkpoint(TEST_NOTE_ID, "first commit, note1", null); + assertThat(notebookRepo.revisionHistory(TEST_NOTE_ID, null).size()).isEqualTo(1); + notebookRepo.checkpoint(TEST_NOTE_ID2, "first commit, note2", null); + assertThat(notebookRepo.revisionHistory(TEST_NOTE_ID2, null).size()).isEqualTo(1); + + //modify, save and checkpoint first note + Note note = notebookRepo.get(TEST_NOTE_ID, null); + Paragraph p = note.addParagraph(); + Map<String, Object> config = p.getConfig(); + config.put("enabled", true); + p.setConfig(config); + p.setText("%md note1 test text"); + notebookRepo.save(note, null); + assertThat(notebookRepo.checkpoint(TEST_NOTE_ID, "second commit, note1", null)).isNotNull(); + assertThat(notebookRepo.revisionHistory(TEST_NOTE_ID, null).size()).isEqualTo(2); + assertThat(notebookRepo.revisionHistory(TEST_NOTE_ID2, null).size()).isEqualTo(1); + assertThat(notebookRepo.checkpoint(TEST_NOTE_ID2, "first commit, note2", null)).isNull(); + assertThat(notebookRepo.revisionHistory(TEST_NOTE_ID2, null).size()).isEqualTo(1); + + //modify, save and checkpoint second note + note = notebookRepo.get(TEST_NOTE_ID2, null); + p = note.addParagraph(); + config = p.getConfig(); + config.put("enabled", false); + p.setConfig(config); + p.setText("%md note2 test text"); + notebookRepo.save(note, null); + assertThat(notebookRepo.checkpoint(TEST_NOTE_ID2, "second commit, note2", null)).isNotNull(); + assertThat(notebookRepo.revisionHistory(TEST_NOTE_ID, null).size()).isEqualTo(2); + assertThat(notebookRepo.revisionHistory(TEST_NOTE_ID2, null).size()).isEqualTo(2); + } + + @Test + public void addCheckpointTest() throws IOException { // initial checks notebookRepo = new GitNotebookRepo(conf); assertThat(notebookRepo.list(null)).isNotEmpty(); http://git-wip-us.apache.org/repos/asf/zeppelin/blob/5cdc02d3/zeppelin-zengine/src/test/resources/2A94M5J2Z/note.json ---------------------------------------------------------------------- diff --git a/zeppelin-zengine/src/test/resources/2A94M5J2Z/note.json b/zeppelin-zengine/src/test/resources/2A94M5J2Z/note.json new file mode 100644 index 0000000..79fe35c --- /dev/null +++ b/zeppelin-zengine/src/test/resources/2A94M5J2Z/note.json @@ -0,0 +1,87 @@ +{ + "paragraphs": [ + { + "text": "%md\n## Congratulations, it\u0027s done.\n##### You can create your own notebook in \u0027Notebook\u0027 menu. Good luck!", + "config": { + "colWidth": 12.0, + "graph": { + "mode": "table", + "height": 300.0, + "optionOpen": false, + "keys": [], + "values": [], + "groups": [], + "scatter": {} + }, + "editorHide": true + }, + "settings": { + "params": {}, + "forms": {} + }, + "jobName": "paragraph_1423836268492_216498320", + "id": "20150213-230428_1231780373", + "result": { + "code": "SUCCESS", + "type": "HTML", + "msg": "\u003ch2\u003eCongratulations, it\u0027s done.\u003c/h2\u003e\n\u003ch5\u003eYou can create your own notebook in \u0027Notebook\u0027 menu. Good luck!\u003c/h5\u003e\n" + }, + "dateCreated": "Feb 13, 2015 11:04:28 PM", + "dateStarted": "Apr 1, 2015 9:12:18 PM", + "dateFinished": "Apr 1, 2015 9:12:18 PM", + "status": "FINISHED", + "progressUpdateIntervalMs": 500 + }, + { + "text": "%md\n\nAbout bank data\n\n```\nCitation Request:\n This dataset is public available for research. The details are described in [Moro et al., 2011]. \n Please include this citation if you plan to use this database:\n\n [Moro et al., 2011] S. Moro, R. Laureano and P. Cortez. Using Data Mining for Bank Direct Marketing: An Application of the CRISP-DM Methodology. \n In P. Novais et al. (Eds.), Proceedings of the European Simulation and Modelling Conference - ESM\u00272011, pp. 117-121, Guimarães, Portugal, October, 2011. EUROSIS.\n\n Available at: [pdf] http://hdl.handle.net/1822/14838\n [bib] http://www3.dsi.uminho.pt/pcortez/bib/2011-esm-1.txt\n```", + "config": { + "colWidth": 12.0, + "graph": { + "mode": "table", + "height": 300.0, + "optionOpen": false, + "keys": [], + "values": [], + "groups": [], + "scatter": {} + }, + "editorHide": true + }, + "settings": { + "params": {}, + "forms": {} + }, + "jobName": "paragraph_1427420818407_872443482", + "id": "20150326-214658_12335843", + "result": { + "code": "SUCCESS", + "type": "HTML", + "msg": "\u003cp\u003eAbout bank data\u003c/p\u003e\n\u003cpre\u003e\u003ccode\u003eCitation Request:\n This dataset is public available for research. The details are described in [Moro et al., 2011]. \n Please include this citation if you plan to use this database:\n\n [Moro et al., 2011] S. Moro, R. Laureano and P. Cortez. Using Data Mining for Bank Direct Marketing: An Application of the CRISP-DM Methodology. \n In P. Novais et al. (Eds.), Proceedings of the European Simulation and Modelling Conference - ESM\u00272011, pp. 117-121, Guimarães, Portugal, October, 2011. EUROSIS.\n\n Available at: [pdf] http://hdl.handle.net/1822/14838\n [bib] http://www3.dsi.uminho.pt/pcortez/bib/2011-esm-1.txt\n\u003c/code\u003e\u003c/pre\u003e\n" + }, + "dateCreated": "Mar 26, 2015 9:46:58 PM", + "dateStarted": "Jul 3, 2015 1:44:56 PM", + "dateFinished": "Jul 3, 2015 1:44:56 PM", + "status": "FINISHED", + "progressUpdateIntervalMs": 500 + }, + { + "config": {}, + "settings": { + "params": {}, + "forms": {} + }, + "jobName": "paragraph_1435955447812_-158639899", + "id": "20150703-133047_853701097", + "dateCreated": "Jul 3, 2015 1:30:47 PM", + "status": "READY", + "progressUpdateIntervalMs": 500 + } + ], + "name": "Sample note - excerpt from Zeppelin Tutorial", + "id": "2A94M5J2Z", + "angularObjects": {}, + "config": { + "looknfeel": "default" + }, + "info": {} +} \ No newline at end of file
