Manually merge changes from webpython branch.

This commit is contained in:
Janusch Jacoby
2015-09-15 16:55:16 +02:00
parent db90c9c61f
commit c8253a6ba0
6 changed files with 576 additions and 29 deletions

View File

@ -20,6 +20,14 @@ $(function() {
var qa_api = undefined;
var output_mode_is_streaming = true;
var websocket,
turtlescreen,
numMessages = 0,
turtlecanvas = $('#turtlecanvas'),
prompt = $('#prompt'),
commands = ['input', 'write', 'turtle', 'turtlebatch'],
streams = ['stdin', 'stdout', 'stderr'];
var flowrResultHtml = '<div class="panel panel-default"><div id="{{headingId}}" role="tab" class="panel-heading"><h4 class="panel-title"><a data-toggle="collapse" data-parent="#flowrHint" href="#{{collapseId}}" aria-expanded="true" aria-controls="{{collapseId}}"></a></h4></div><div id="{{collapseId}}" role="tabpanel" aria-labelledby="{{headingId}}" class="panel-collapse collapse"><div class="panel-body"></div></div></div>'
var ajax = function(options) {
@ -181,7 +189,13 @@ $(function() {
};
var evaluateCodeWithStreamedResponse = function(url, callback) {
var event_source = new EventSource(url);
initWebsocketConnection(url);
// TODO only init turtle when required
initTurtle();
// TODO reimplement via websocket messsages
/*var event_source = new EventSource(url);
event_source.addEventListener('close', closeEventSource);
event_source.addEventListener('error', closeEventSource);
@ -201,7 +215,7 @@ $(function() {
event_source.addEventListener('status', function(event) {
showStatus(JSON.parse(event.data));
});
});*/
};
var handleStreamedResponseForCodePilot = function(event) {
@ -428,7 +442,7 @@ $(function() {
handleSidebarClick(e);
});
*/
//session
session.on('annotationRemoval', handleAnnotationRemoval);
session.on('annotationChange', handleAnnotationChange);
@ -1065,6 +1079,183 @@ $(function() {
$('#request-for-comments').toggle(isActiveFileSubmission() && !isActiveFileBinary());
};
var initWebsocketConnection = function(url) {
websocket = new WebSocket('ws://' + window.location.hostname + ':' + window.location.port + url);
websocket.onopen = function(evt) { onWebSocketOpen(evt) };
websocket.onclose = function(evt) { onWebSocketClose(evt) };
websocket.onmessage = function(evt) { onWebSocketMessage(evt) };
websocket.onerror = function(evt) { onWebSocketError(evt) };
websocket.flush = function() { this.send('\n'); }
};
var initTurtle = function() {
turtlescreen = new Turtle(websocket, $('#turtlecanvas'));
};
var initCallbacks = function() {
if ($('#run').isPresent()) {
$('#run').bind('click', function(event) {
hideCanvas();
hidePrompt();
});
}
if ($('#prompt').isPresent()) {
$('#prompt').on('keypress', handlePromptKeyPress);
$('#prompt-submit').on('click', submitPromptInput);
}
}
var onWebSocketOpen = function(evt) {
//alert("Session started");
};
var onWebSocketClose = function(evt) {
//alert("Session terminated");
};
var onWebSocketMessage = function(evt) {
numMessages++;
parseCanvasMessage(evt.data, true);
};
var onWebSocketError = function(evt) {
//alert("Something went wrong.")
};
var executeCommand = function(msg) {
if ($.inArray(msg.cmd, commands) == -1) {
console.log("Unknown command: " + msg.cmd);
// skipping unregistered commands is required
// as we may receive mirrored response due to internal behaviour
return;
}
switch(msg.cmd) {
case 'input':
showPrompt();
break;
case 'write':
printWebsocketOutput(msg);
break;
case 'turtle':
showCanvas();
handleTurtleCommand(msg);
break;
case 'turtlebatch':
showCanvas();
handleTurtlebatchCommand(msg);
break;
}
};
// todo reuse method from editor.js
var printWebsocketOutput = function(msg) {
var element = findOrCreateOutputElement(0);
console.log(element);
switch (msg.stream) {
case 'internal':
element.addClass('text-danger');
break;
case 'stderr':
element.addClass('text-warning');
break;
case 'stdout':
case 'stdin': // for eventual prompts
default:
element.addClass('text-muted');
}
element.append(msg.data)
};
var handleTurtleCommand = function(msg) {
if (msg.action in turtlescreen) {
result = turtlescreen[msg.action].apply(turtlescreen, msg.args);
websocket.send(JSON.stringify({cmd: 'result', 'result': result}));
} else {
websocket.send(JSON.stringify({cmd: 'exception', exception: 'AttributeError', message: msg.action}));
}
websocket.flush();
};
var handleTurtlebatchCommand = function(msg) {
for (i = 0; i < msg.batch.length; i++) {
cmd = msg.batch[i];
turtlescreen[cmd[0]].apply(turtlescreen, cmd[1]);
}
};
var handlePromptKeyPress = function(evt) {
if (evt.which === ENTER_KEY_CODE) {
submitPromptInput();
}
}
var submitPromptInput = function() {
var input = $('#prompt-input');
var message = input.val();
websocket.send(JSON.stringify({cmd: 'result', 'data': message}));
websocket.flush();
input.val('');
hidePrompt();
}
var parseCanvasMessage = function(message, recursive) {
var msg;
message = message.replace(/^\s+|\s+$/g, "");
try {
// todo validate json instead of catching
msg = JSON.parse(message);
} catch (e) {
if (!recursive) {
return false;
}
// why does docker sometimes send multiple commands at once?
message = message.replace(/^\s+|\s+$/g, "");
messages = message.split("\n");
for (var i = 0; i < messages.length; i++) {
if (!messages[i]) {
continue;
}
parseCanvasMessage(messages[i], false);
}
return;
}
executeCommand(msg);
};
var showPrompt = function() {
if (prompt.isPresent() && prompt.hasClass('hidden')) {
prompt.removeClass('hidden');
}
prompt.focus();
}
var hidePrompt = function() {
if (prompt.isPresent() && !prompt.hasClass('hidden')) {
console.log("hiding prompt2");
prompt.addClass('hidden');
}
}
var showCanvas = function() {
if ($('#turtlediv').isPresent()
&& turtlecanvas.hasClass('hidden')) {
// initialize two-column layout
$('#output-col1').addClass('col-lg-7 col-md-7 two-column');
turtlecanvas.removeClass('hidden');
}
};
var hideCanvas = function() {
if ($('#turtlediv').isPresent()
&& !(turtlecanvas.hasClass('hidden'))) {
output = $('#output-col1');
if (output.hasClass('two-column')) {
output.removeClass('col-lg-7 col-md-7 two-column');
}
turtlecanvas.addClass('hidden');
}
};
var requestComments = function(e) {
var user_id = $('#editor').data('user-id')
var exercise_id = $('#editor').data('exercise-id')