Merge remote-tracking branch 'origin/master' into flowr

# Conflicts:
#	app/assets/javascripts/editor/evaluation.js
#	app/assets/javascripts/editor/participantsupport.js
#	app/views/exercises/_editor_output.html.slim
#	config/code_ocean.yml.example
#	config/routes.rb
This commit is contained in:
Maximilian Grundke
2018-11-28 13:14:21 +01:00
500 changed files with 12187 additions and 3430 deletions

View File

@@ -33,6 +33,7 @@ var CodeOceanEditor = {
<% @config ||= CodeOcean::Config.new(:code_ocean).read(erb: false) %>
sendEvents: <%= @config['codeocean_events'] ? @config['codeocean_events']['enabled'] : false %>,
eventURL: "<%= @config['codeocean_events'] ? events_path : '' %>",
fileTypeURL: "<%= file_types_path %>",
configureEditors: function () {
@@ -43,7 +44,7 @@ configureEditors: function () {
confirmDestroy: function (event) {
event.preventDefault();
if (confirm($(this).data('message-confirm'))) {
if (confirm($(event.target).data('message-confirm'))) {
this.destroyFile();
}
},
@@ -63,7 +64,7 @@ configureEditors: function () {
if ($('#output-' + index).isPresent()) {
return $('#output-' + index);
} else {
var element = $('<pre>').attr('id', 'output-' + index);
var element = $('<pre class="mt-2">').attr('id', 'output-' + index);
$('#output').append(element);
return element;
}
@@ -79,13 +80,13 @@ configureEditors: function () {
}
},
getPanelClass: function (result) {
getCardClass: function (result) {
if (result.stderr && !result.score) {
return 'panel-danger';
return 'card bg-danger text-white';
} else if (result.score < 1) {
return 'panel-warning';
return 'card bg-warning text-white';
} else {
return 'panel-success';
return 'card bg-success text-white';
}
},
@@ -107,11 +108,22 @@ configureEditors: function () {
progress_bar.css('width', percentage + '%');
},
// The event ready.jstree is fired too early and thus doesn't work.
selectFileInJsTree: function(filetree, file_id) {
if (!filetree.hasClass('jstree-loading')) {
filetree.jstree("deselect_all");
filetree.jstree().select_node(file_id);
} else {
setTimeout(this.selectFileInJsTree.bind(null, filetree, file_id), 250);
}
},
showFirstFile: function() {
var frame = $('.frame[data-role="main_file"]').isPresent() ? $('.frame[data-role="main_file"]') : $('.frame').first();
var file_id = frame.find('.editor').data('file-id');
this.setActiveFile(frame.data('filename'), file_id);
$('#files').jstree().select_node(file_id);
var filetree = $('#files');
this.selectFileInJsTree(filetree, file_id);
this.showFrame(frame);
this.toggleButtonStates();
},
@@ -124,11 +136,11 @@ configureEditors: function () {
getProgressBarClass: function (percentage) {
if (percentage < this.ADEQUATE_PERCENTAGE) {
return 'progress-bar progress-bar-striped progress-bar-danger';
return 'progress-bar progress-bar-striped bg-danger';
} else if (percentage < this.SUCCESSFULL_PERCENTAGE) {
return 'progress-bar progress-bar-striped progress-bar-warning';
return 'progress-bar progress-bar-striped bg-warning';
} else {
return 'progress-bar progress-bar-striped progress-bar-success';
return 'progress-bar progress-bar-striped bg-success';
}
},
@@ -158,7 +170,7 @@ configureEditors: function () {
category: 'editor_paste',
data: pasteObject.text,
exercise_id: $('#editor').data('exercise-id'),
file_id: $(this).data('file-id')
file_id: $(event.target).data('file-id')
});
}
},
@@ -177,8 +189,8 @@ configureEditors: function () {
},
resizeParentOfAceEditor: function (element){
// calculate needed size: window height - position of top of button-bar - 60 for bar itself and margins
var windowHeight = window.innerHeight - $('#editor-buttons').offset().top - 60;
// calculate needed size: window height - position of top of ACE editor - height of autosave label below editor - 5 for bar margins
var windowHeight = window.innerHeight - $(element).offset().top - $('#autosave-label').height() - 5;
$(element).parent().height(windowHeight);
},
@@ -266,14 +278,29 @@ configureEditors: function () {
this.initializeRequestForComments()
},
updateEditorModeToFileTypeID: function (editor, fileTypeID) {
var newMode = 'ace/mode/text'
$.ajax(this.fileTypeURL + '/' + fileTypeID, {
dataType: 'json'
}).done(function (data) {
if (data['editor_mode'] !== null) {
newMode = data['editor_mode'];
}
}).fail(_.noop)
.always(function () {
ace.edit(editor).session.setMode(newMode);
});
},
initializeFileTree: function () {
$('#files').jstree($('#files').data('entries'));
$('#files').on('click', 'li.jstree-leaf', function (event) {
active_file = {
filename: $(event.target).parent().text(),
id: parseInt($(event.target).parent().attr('id'))
};
var frame = $('[data-file-id="' + active_file.id + '"]').parent();
this.setActiveFile(
$(event.target).parent().text(),
parseInt($(event.target).parent().attr('id'))
);
var frame = $('[data-file-id="' + this.active_file.id + '"]').parent();
this.showFrame(frame);
this.toggleButtonStates();
}.bind(this));
@@ -296,8 +323,8 @@ configureEditors: function () {
handleSideBarToggle: function() {
$('#sidebar').toggleClass('sidebar-col').toggleClass('sidebar-col-collapsed');
$('#sidebar-collapsed').toggleClass('hidden');
$('#sidebar-uncollapsed').toggleClass('hidden');
$('#sidebar-collapsed').toggleClass('d-none');
$('#sidebar-uncollapsed').toggleClass('d-none');
},
initializeRegexes: function () {
@@ -369,17 +396,17 @@ configureEditors: function () {
return Modernizr.websockets;
},
populatePanel: function (panel, result, index) {
panel.removeClass('panel-default').addClass(this.getPanelClass(result));
panel.find('.panel-title .filename').text(result.filename);
panel.find('.panel-title .number').text(index + 1);
panel.find('.row .col-sm-9').eq(0).find('.number').eq(0).text(result.passed);
panel.find('.row .col-sm-9').eq(0).find('.number').eq(1).text(result.count);
panel.find('.row .col-sm-9').eq(1).find('.number').eq(0).text(parseFloat((result.score * result.weight).toFixed(2)));
panel.find('.row .col-sm-9').eq(1).find('.number').eq(1).text(result.weight);
panel.find('.row .col-sm-9').eq(2).html(result.message);
if (result.error_messages) panel.find('.row .col-sm-9').eq(3).text(result.error_messages.join(' '));
//panel.find('.row .col-sm-9').eq(4).find('a').attr('href', '#output-' + index);
populateCard: function (card, result, index) {
card.addClass(this.getCardClass(result));
card.find('.card-title .filename').text(result.filename);
card.find('.card-title .number').text(index + 1);
card.find('.row .col-sm-9').eq(0).find('.number').eq(0).text(result.passed);
card.find('.row .col-sm-9').eq(0).find('.number').eq(1).text(result.count);
card.find('.row .col-sm-9').eq(1).find('.number').eq(0).text(parseFloat((result.score * result.weight).toFixed(2)));
card.find('.row .col-sm-9').eq(1).find('.number').eq(1).text(result.weight);
card.find('.row .col-sm-9').eq(2).html(result.message);
if (result.error_messages) card.find('.row .col-sm-9').eq(3).text(result.error_messages.join(' '));
//card.find('.row .col-sm-9').eq(4).find('a').attr('href', '#output-' + index);
},
publishCodeOceanEvent: function (payload) {
@@ -409,7 +436,7 @@ configureEditors: function () {
url: $('#editor').data('errors-url')
});
jqxhr.always(this.hideSpinner);
jqxhr.success(this.renderHint);
jqxhr.done(this.renderHint);
},
toggleButtonStates: function () {
@@ -556,14 +583,14 @@ configureEditors: function () {
},
showOutputBar: function() {
$('#output_sidebar_collapsed').addClass('hidden');
$('#output_sidebar_uncollapsed').removeClass('hidden');
$('#output_sidebar_collapsed').addClass('d-none');
$('#output_sidebar_uncollapsed').removeClass('d-none');
$('#output_sidebar').removeClass('output-col-collapsed').addClass('output-col');
},
hideOutputBar: function() {
$('#output_sidebar_collapsed').removeClass('hidden');
$('#output_sidebar_uncollapsed').addClass('hidden');
$('#output_sidebar_collapsed').removeClass('d-none');
$('#output_sidebar_uncollapsed').addClass('d-none');
$('#output_sidebar').removeClass('output-col').addClass('output-col-collapsed');
},
@@ -572,16 +599,17 @@ configureEditors: function () {
},
initializeDescriptionToggle: function() {
$('#exercise-headline').on('click', this.toggleDescriptionPanel.bind(this));
$('a#toggle').on('click', this.toggleDescriptionPanel.bind(this));
$('#exercise-headline').on('click', this.toggleDescriptionCard.bind(this));
$('a#toggle').on('click', this.toggleDescriptionCard.bind(this));
},
toggleDescriptionPanel: function() {
$('#description-panel').toggleClass('description-panel-collapsed').toggleClass('description-panel');
toggleDescriptionCard: function() {
$('#description-card').toggleClass('description-card-collapsed').toggleClass('description-card');
$('#description-symbol').toggleClass('fa-chevron-down').toggleClass('fa-chevron-right');
var toggle = $('a#toggle');
toggle.text(toggle.text() == toggle.data('hide') ? toggle.data('show') : toggle.data('hide'));
this.resizeAceEditors();
event.preventDefault();
},
/**

View File

@@ -9,7 +9,7 @@ CodeOceanEditorEvaluation = {
this.clearScoringOutput();
this.createSubmission('#assess', null, function (response) {
this.showSpinner($('#assess'));
$('#score_div').removeClass('hidden');
$('#score_div').removeClass('d-none');
var url = response.score_url;
this.initializeSocketForScoring(url);
}.bind(this));
@@ -26,9 +26,9 @@ CodeOceanEditorEvaluation = {
printScoringResult: function (result, index) {
$('#results').show();
var panel = $('#dummies').children().first().clone();
this.populatePanel(panel, result, index);
$('#results ul').first().append(panel);
var card = $('#dummies').children().first().clone();
this.populateCard(card, result, index);
$('#results ul').first().append(card);
},
printScoringResults: function (response) {
@@ -60,7 +60,7 @@ CodeOceanEditorEvaluation = {
renderHint: function (object) {
var hint = object.data || object.hint;
if (hint) {
$('#hint .panel-body').text(hint);
$('#hint .card-body').text(hint);
$('#hint').fadeIn();
}
},
@@ -152,22 +152,22 @@ CodeOceanEditorEvaluation = {
var element = this.findOrCreateOutputElement(index);
if (!colorize) {
if (output.stdout != undefined && output.stdout != '') {
element.append(output.stdout)
//element.text(element.text() + output.stdout)
//element.append(output.stdout)
element.text(element.text() + output.stdout)
}
if (output.stderr != undefined && output.stderr != '') {
element.append('StdErr: ' + output.stderr);
//element.text('StdErr: ' + element.text() + output.stderr);
//element.append('StdErr: ' + output.stderr);
element.text('StdErr: ' + element.text() + output.stderr);
}
} else if (output.stderr) {
element.addClass('text-warning').append(output.stderr);
//element.addClass('text-warning').text(element.text() + output.stderr);
//element.addClass('text-warning').append(output.stderr);
element.addClass('text-warning').text(element.text() + output.stderr);
this.QaApiOutputBuffer.stderr += output.stderr;
} else if (output.stdout) {
element.addClass('text-success').append(output.stdout);
//element.addClass('text-success').text(element.text() + output.stdout);
//element.addClass('text-success').append(output.stdout);
element.addClass('text-success').text(element.text() + output.stdout);
this.QaApiOutputBuffer.stdout += output.stdout;
} else {
element.addClass('text-muted').text($('#output').data('message-no-output'));

View File

@@ -2,8 +2,9 @@ CodeOceanEditorWebsocket = {
websocket: null,
createSocketUrl: function(url) {
var sockURL = new URL(window.location);
sockURL.pathname = url;
var sockURL = new URL(url, window.location);
// not needed any longer, we put it directly into the url: sockURL.pathname = url;
// sanitize socket protocol string, strip trailing slash and other malicious chars if they are there
sockURL.protocol = '<%= DockerClient.config['ws_client_protocol']&.match(/(\w+):*\/*/)&.to_a&.at(1) %>:';

View File

@@ -90,7 +90,6 @@ CodeOceanEditorFlowr = {
var collapsibleTileHtml = self.flowrResultHtml
.replace(/{{collapseId}}/g, 'collapse-' + index).replace(/{{headingId}}/g, 'heading-' + index);
var resultTile = $(collapsibleTileHtml);
var questionUrl = 'https://stackoverflow.com/questions/' + result.question_id;
var header = resultTile.find('h4 > a');
@@ -162,7 +161,7 @@ CodeOceanEditorRequestForComments = {
$.flash.success({text: $('#askForCommentsButton').data('message-success')});
// trigger a run
this.runSubmission.call(this, submission);
}.bind(this)).error(this.ajaxError.bind(this));
}.bind(this)).fail(this.ajaxError.bind(this));
};
this.createSubmission($('#requestComments'), null, createRequestForComments.bind(this));

View File

@@ -2,19 +2,19 @@ CodeOceanEditorPrompt = {
prompt: '#prompt',
showPrompt: function(msg) {
var label = $('#prompt .input-group-addon');
var label = $('#prompt .input-group-text');
var prompt = $(this.prompt);
label.text(msg.data || label.data('prompt'));
if (prompt.isPresent() && prompt.hasClass('hidden')) {
prompt.removeClass('hidden');
if (prompt.isPresent() && prompt.hasClass('d-none')) {
prompt.removeClass('d-none');
}
$('#prompt input').focus();
},
hidePrompt: function() {
var prompt = $(this.prompt);
if (prompt.isPresent() && !prompt.hasClass('hidden')) {
prompt.addClass('hidden');
if (prompt.isPresent() && !prompt.hasClass('d-none')) {
prompt.addClass('d-none');
}
},

View File

@@ -106,14 +106,16 @@ CodeOceanEditorSubmissions = {
this.ajax({
method: 'GET',
url: $('#start-over').data('url')
}).success(function(response) {
}).done(function(response) {
this.hideSpinner();
_.each(this.editors, function(editor) {
var file_id = $(editor.container).data('file-id');
var file = _.find(response.files, function(file) {
return file.id === file_id;
});
editor.setValue(file.content);
if(file){
editor.setValue(file.content);
}
}.bind(this));
}.bind(this));
},
@@ -153,7 +155,7 @@ CodeOceanEditorSubmissions = {
$('#stop').data('url', submission.stop_url);
this.running = true;
this.showSpinner($('#run'));
$('#score_div').addClass('hidden');
$('#score_div').addClass('d-none');
this.toggleButtonStates();
var url = submission.run_url.replace(this.FILENAME_URL_PLACEHOLDER, this.active_file.filename.replace(/#$/,'')); // remove # if it is the last character, this is not part of the filename and just an anchor
this.initializeSocketForRunning(url);
@@ -173,8 +175,8 @@ CodeOceanEditorSubmissions = {
if ($('#test').is(':visible')) {
this.createSubmission('#test', null, function(response) {
this.showSpinner($('#test'));
$('#score_div').addClass('hidden');
var url = response.test_url.replace(this.FILENAME_URL_PLACEHOLDER, this.active_file.filenamereplace(/#$/,'')); // remove # if it is the last character, this is not part of the filename and just an anchor
$('#score_div').addClass('d-none');
var url = response.test_url.replace(this.FILENAME_URL_PLACEHOLDER, this.active_file.filename.replace(/#$/,'')); // remove # if it is the last character, this is not part of the filename and just an anchor
this.initializeSocketForTesting(url);
}.bind(this));
}

View File

@@ -38,10 +38,10 @@ CodeOceanEditorTurtle = {
showCanvas: function () {
if ($('#turtlediv').isPresent()
&& this.turtlecanvas.hasClass('hidden')) {
&& this.turtlecanvas.hasClass('d-none')) {
// initialize two-column layout
$('#output-col1').addClass('col-lg-7 col-md-7 two-column');
this.turtlecanvas.removeClass('hidden');
this.turtlecanvas.removeClass('d-none');
}
}