Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,9 @@ public void onMessage(NotebookSocket conn, String msg) {
case LIST_REVISION_HISTORY:
listRevisionHistory(conn, notebook, messagereceived);
break;
case SET_NOTE_REVISION:
setNoteRevision(conn, userAndRoles, notebook, messagereceived);
break;
case NOTE_REVISION:
getNoteByRevision(conn, notebook, messagereceived);
break;
Expand Down Expand Up @@ -1473,6 +1476,46 @@ private void listRevisionHistory(NotebookSocket conn, Notebook notebook,
conn.send(serializeMessage(new Message(OP.LIST_REVISION_HISTORY)
.put("revisionList", revisions)));
}

private void setNoteRevision(NotebookSocket conn, HashSet<String> userAndRoles,
Notebook notebook, Message fromMessage) throws IOException {

String noteId = (String) fromMessage.get("noteId");
String revisionId = (String) fromMessage.get("revisionId");
AuthenticationInfo subject = new AuthenticationInfo(fromMessage.principal);

NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization();
if (!notebookAuthorization.isWriter(noteId, userAndRoles)) {
permissionError(conn, "update", fromMessage.principal,
userAndRoles, notebookAuthorization.getWriters(noteId));
return;
}

Note headNote = null;
boolean setRevisionStatus;
try {
headNote = notebook.setNoteRevision(noteId, revisionId, subject);
setRevisionStatus = headNote != null;
} catch (Exception e) {
setRevisionStatus = false;
LOG.error("Failed to set given note revision", e);
}
if (setRevisionStatus) {
notebook.loadNoteFromRepo(noteId, subject);
}

conn.send(serializeMessage(new Message(OP.SET_NOTE_REVISION)
.put("status", setRevisionStatus)));

if (setRevisionStatus) {
Note reloadedNote = notebook.getNote(headNote.getId());
broadcastNote(reloadedNote);
} else {
conn.send(serializeMessage(new Message(OP.ERROR_INFO).put("info",
"Couldn't set note to the given revision. "
+ "Please check the logs for more details.")));
}
}

private void getNoteByRevision(NotebookSocket conn, Notebook notebook, Message fromMessage)
throws IOException {
Expand All @@ -1483,7 +1526,7 @@ private void getNoteByRevision(NotebookSocket conn, Notebook notebook, Message f
conn.send(serializeMessage(new Message(OP.NOTE_REVISION)
.put("noteId", noteId)
.put("revisionId", revisionId)
.put("data", revisionNote)));
.put("note", revisionNote)));
}

/**
Expand Down
4 changes: 4 additions & 0 deletions zeppelin-web/src/app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@
templateUrl: 'app/notebook/notebook.html',
controller: 'NotebookCtrl'
})
.when('/notebook/:noteId/revision/:revisionId', {
templateUrl: 'app/notebook/notebook.html',
controller: 'NotebookCtrl'
})
.when('/jobmanager', {
templateUrl: 'app/jobmanager/jobmanager.html',
controller: 'JobmanagerCtrl'
Expand Down
15 changes: 12 additions & 3 deletions zeppelin-web/src/app/notebook/notebook-actionBar.html
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ <h3>
tooltip-placement="bottom" tooltip="Version control">
<i class="fa fa-file-code-o"></i>
</button>
<button type="button"
class="btn btn-default btn-xs"
id="setRevision"
ng-hide="viewOnly"
ng-click="setNoteRevision()"
ng-disabled="revisionDisabled"
tooltip-placement="bottom" tooltip="Set revision">
<i class="fa fa-arrow-circle-o-right"></i>
</button>
<ul class="dropdown-menu" style="width:250px"
aria-labelledby="versionControlDropdown">
<li>
Expand All @@ -101,8 +110,8 @@ <h3>
</ul>
</div>
<div class="btn-group" role="group">
<button type="button" class="btn btn-default btn-xs revisionName">
Head
<button type="button" class="btn btn-default btn-xs revisionName" title="{{currentRevision}}">
<div style="overflow: hidden">{{currentRevision}}</div>
</button>
<button type="button" ng-if="noteRevisions.length > 0"
class="btn btn-default dropdown-toggle caretSeparator"
Expand All @@ -111,7 +120,7 @@ <h3>
</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">
<a style="cursor:pointer" ng-click="visitRevision(revision)">
<span style="display: block;">
<strong>{{revision.message}}</strong>
</span>
Expand Down
66 changes: 61 additions & 5 deletions zeppelin-web/src/app/notebook/notebook.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,14 @@
$scope.saveTimer = null;

var connectedOnce = false;
var isRevisionPath = function(path) {
var pattern = new RegExp('^.*\/notebook\/[a-zA-Z0-9_]*\/revision\/[a-zA-Z0-9_]*');
return pattern.test(path);
};

// user auto complete related
$scope.noteRevisions = [];
$scope.currentRevision = 'Head';
$scope.revisionDisabled = !isRevisionPath($location.path());

$scope.$on('setConnectedStatus', function(event, param) {
if (connectedOnce && param) {
Expand All @@ -89,7 +94,11 @@
/** Init the new controller */
var initNotebook = function() {
noteVarShareService.clear();
websocketMsgSrv.getNote($routeParams.noteId);
if ($routeParams.revisionId) {
websocketMsgSrv.getNoteByRevision($routeParams.noteId, $routeParams.revisionId);
} else {
websocketMsgSrv.getNote($routeParams.noteId);
}
websocketMsgSrv.listRevisionHistory($routeParams.noteId);
var currentRoute = $route.current;
if (currentRoute) {
Expand Down Expand Up @@ -187,17 +196,64 @@
document.getElementById('note.checkpoint.message').value = '';
};

// set notebook head to given revision
$scope.setNoteRevision = function() {
BootstrapDialog.confirm({
closable: true,
title: '',
message: 'Set notebook head to current revision?',
callback: function(result) {
if (result) {
websocketMsgSrv.setNoteRevision($routeParams.noteId, $routeParams.revisionId);
}
}
});
};

$scope.$on('listRevisionHistory', function(event, data) {
console.log('We got the revisions %o', data);
console.log('received list of revisions %o', data);
$scope.noteRevisions = data.revisionList;
$scope.noteRevisions.splice(0, 0, {
id: 'Head',
message: 'Head'
});
if ($routeParams.revisionId) {
var index = _.findIndex($scope.noteRevisions, {'id': $routeParams.revisionId});
if (index > -1) {
$scope.currentRevision = $scope.noteRevisions[index].message;
}
}
});

// receive certain revision of note
$scope.$on('noteRevision', function(event, data) {
console.log('received note revision %o', data);
//TODO(xxx): render it
if (data.note) {
$scope.note = data.note;
} else {
$location.path('/');
}
});

$scope.$on('setNoteRevisionResult', function(event, data) {
console.log('received set note revision result %o', data);
if (data.status) {
$location.path('/notebook/' + $routeParams.noteId);
}
});

$scope.visitRevision = function(revision) {
if (revision.id) {
if (revision.id === 'Head') {
$location.path('/notebook/' + $routeParams.noteId);
} else {
$location.path('/notebook/' + $routeParams.noteId + '/revision/' + revision.id);
}
} else {
ngToast.danger({content: 'There is a problem with this Revision',
verticalPosition: 'top', dismissOnTimeout: false});
}
};

$scope.runNote = function() {
BootstrapDialog.confirm({
closable: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@
$rootScope.$broadcast('moveParagraph', data.id, data.index);
} else if (op === 'NOTE_UPDATED') {
$rootScope.$broadcast('updateNote', data.name, data.config, data.info);
} else if (op === 'SET_NOTE_REVISION') {
$rootScope.$broadcast('setNoteRevisionResult', data);
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,16 @@
});
},

setNoteRevision: function(noteId, revisionId) {
websocketEvents.sendNewEvent({
op: 'SET_NOTE_REVISION',
data: {
noteId: noteId,
revisionId: revisionId
}
});
},

listRevisionHistory: function(noteId) {
websocketEvents.sendNewEvent({
op: 'LIST_REVISION_HISTORY',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,11 @@ public List<Revision> listRevisionHistory(String noteId,
return notebookRepo.revisionHistory(noteId, subject);
}

public Note setNoteRevision(String noteId, String revisionId, AuthenticationInfo subject)
throws IOException {
return notebookRepo.setNoteRevision(noteId, revisionId, subject);
}

public Note getNoteByRevision(String noteId, String revisionId, AuthenticationInfo subject)
throws IOException {
return notebookRepo.get(noteId, revisionId, subject);
Expand Down Expand Up @@ -432,7 +437,7 @@ public void convertFromSingleResultToMultipleResultsFormat(Note note) {
}

@SuppressWarnings("rawtypes")
private Note loadNoteFromRepo(String id, AuthenticationInfo subject) {
public Note loadNoteFromRepo(String id, AuthenticationInfo subject) {
Note note = null;
try {
note = notebookRepo.get(id, subject);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,4 +250,11 @@ public List<NotebookRepoSettingsInfo> getSettings(AuthenticationInfo subject) {
public void updateSettings(Map<String, String> settings, AuthenticationInfo subject) {
LOG.warn("Method not implemented");
}

@Override
public Note setNoteRevision(String noteId, String revId, AuthenticationInfo subject)
throws IOException {
// Auto-generated method stub
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,16 @@ public List<Revision> revisionHistory(String noteId, AuthenticationInfo subject)
return history;
}

@Override
public Note setNoteRevision(String noteId, String revId, AuthenticationInfo subject)
throws IOException {
Note revisionNote = get(noteId, revId, subject);
if (revisionNote != null) {
save(revisionNote, subject);
}
return revisionNote;
}

@Override
public void close() {
git.getRepository().close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,18 @@ public interface NotebookRepo {
*/
@ZeppelinApi public List<Revision> revisionHistory(String noteId, AuthenticationInfo subject);

/**
* Set note to particular revision.
*
* @param noteId Id of the Notebook
* @param rev revision of the Notebook
* @return a Notebook
* @throws IOException
*/
@ZeppelinApi
public Note setNoteRevision(String noteId, String revId, AuthenticationInfo subject)
throws IOException;

/**
* Get NotebookRepo settings got the given user.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -498,4 +498,25 @@ public void updateSettings(Map<String, String> settings, AuthenticationInfo subj
LOG.error("Cannot update notebook repo settings", e);
}
}

@Override
public Note setNoteRevision(String noteId, String revId, AuthenticationInfo subject)
throws IOException {
int repoCount = getRepoCount();
int repoBound = Math.min(repoCount, getMaxRepoNum());
Note currentNote = null, revisionNote = null;
for (int i = 0; i < repoBound; i++) {
try {
currentNote = getRepo(i).setNoteRevision(noteId, revId, subject);
} catch (IOException e) {
// already logged
currentNote = null;
}
// second condition assures that fist successful is returned
if (currentNote != null && revisionNote == null) {
revisionNote = currentNote;
}
}
return revisionNote;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -284,4 +284,11 @@ public List<NotebookRepoSettingsInfo> getSettings(AuthenticationInfo subject) {
public void updateSettings(Map<String, String> settings, AuthenticationInfo subject) {
LOG.warn("Method not implemented");
}

@Override
public Note setNoteRevision(String noteId, String revId, AuthenticationInfo subject)
throws IOException {
// Auto-generated method stub
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -331,4 +331,11 @@ public void updateSettings(Map<String, String> settings, AuthenticationInfo subj
}
}

@Override
public Note setNoteRevision(String noteId, String revId, AuthenticationInfo subject)
throws IOException {
// Auto-generated method stub
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -408,4 +408,11 @@ public void updateSettings(Map<String, String> settings, AuthenticationInfo subj
changeToken(instanceId, subject.getUser());
}

@Override
public Note setNoteRevision(String noteId, String revId, AuthenticationInfo subject)
throws IOException {
// Auto-generated method stub
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ public static enum OP {
NOTE_REVISION, // [c-s] get certain revision of note
// @param noteId
// @param revisionId

SET_NOTE_REVISION, // [c-s] set current notebook head to this revision
// @param noteId
// @param revisionId
APP_APPEND_OUTPUT, // [s-c] append output
APP_UPDATE_OUTPUT, // [s-c] update (replace) output
APP_LOAD, // [s-c] on app load
Expand Down
Loading