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

@@ -10,20 +10,18 @@
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//
//= require ace/ace
//= require chosen.jquery.min
//= require jquery-ui.min
//= require d3
//= require jquery.turbolinks
//= require jquery_ujs
//= require jstree/jstree.min
//= require turbolinks
//= require_tree ../../../lib
//= require pagedown_bootstrap
//= require d3
//
// lib/assets
//= require flash
//= require url
//
// vendor/assets
//= require ace/ace
//= require ace/ext-language_tools
//
// app/assets
//= require_tree .
//= require bootstrap_pagedown
//= require markdown.converter
//= require markdown.sanitizer
//= require markdown.editor
//= require ace/ext-language_tools

View File

@@ -8,20 +8,18 @@ window.CodeOcean = {
}
};
$(function() {
var ANIMATION_DURATION = 500;
var ANIMATION_DURATION = 500;
$.isController = function(name) {
return $('.container[data-controller="' + name + '"]').isPresent();
};
$.isController = function(name) {
return $('.container[data-controller="' + name + '"]').isPresent();
};
$.fn.isPresent = function() {
return this.length > 0;
};
$.fn.isPresent = function() {
return this.length > 0;
};
$.fn.scrollTo = function(selector) {
$(this).animate({
scrollTop: $(selector).offset().top - $(this).offset().top + $(this).scrollTop()
}, ANIMATION_DURATION);
};
});
$.fn.scrollTo = function(selector) {
$(this).animate({
scrollTop: $(selector).offset().top - $(this).offset().top + $(this).scrollTop()
}, ANIMATION_DURATION);
};

View File

@@ -1,4 +1,4 @@
$(document).ready(function () {
$(document).on('turbolinks:load', function() {
var subMenusSelector = 'ul.dropdown-menu [data-toggle=dropdown]';
@@ -14,7 +14,7 @@ $(document).ready(function () {
var menu = $(this).parent().find("ul");
var menupos = menu.offset();
var newPos;
var newPos = 0.0;
if ((menupos.left + menu.width()) + 30 > $(window).width()) {
newPos = -menu.width();
} else {

View File

@@ -1,4 +1,4 @@
$(function() {
$(document).on('turbolinks:load', function() {
var CHART_START = window.vis ? vis.moment().add(-1, 'minute') : undefined;
var DEFAULT_REFRESH_INTERVAL = 5000;
@@ -51,6 +51,7 @@ $(function() {
} else {
var jqxhr = $.ajax({
dataType: 'json',
url: '/admin/dashboard',
method: 'GET'
});
jqxhr.done(function(response) {

View File

@@ -1,4 +1,4 @@
$(function() {
$(document).on('turbolinks:load', function() {
//Merge all editor components.
$.extend(

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');
}
}

View File

@@ -1,4 +1,4 @@
$(function() {
$(document).on('turbolinks:load', function() {
if ($.isController('error_templates')) {
$('#add-attribute').find('button').on('click', function () {
$.ajax(location + '/attribute.json', {
@@ -8,9 +8,9 @@ $(function() {
dataType: 'json',
error_template_attribute_id: $('#add-attribute').find('select').val()
}
}).success(function () {
}).done(function () {
location.reload();
}).error(function (error) {
}).fail(function (error) {
$.flash.danger({text: error.statusText});
});
});

View File

@@ -1,4 +1,4 @@
$(function() {
$(document).on('turbolinks:load', function() {
if ($.isController('execution_environments')) {
if ($('.edit_execution_environment, .new_execution_environment').isPresent()) {
new MarkdownEditor('#execution_environment_help');

View File

@@ -1,4 +1,4 @@
$(function() {
$(document).on('turbolinks:load', function() {
if ($.isController('exercise_collections')) {
var dataElement = $('#data');
var exerciseList = $('#exercise-list');

View File

@@ -1,4 +1,4 @@
$(function() {
$(document).on('turbolinks:load', function() {
// /exercises/38/statistics good for testing
if ($.isController('exercises') && $('.graph-functions-2').isPresent()) {

View File

@@ -1,4 +1,4 @@
$(function() {
$(document).on('turbolinks:load', function() {
// ruby part adds the relative_url_root, if it is set.
var ACE_FILES_PATH = '<%= (defined? Rails.application.config.relative_url_root) && Rails.application.config.relative_url_root != nil && Rails.application.config.relative_url_root != "" ? Rails.application.config.relative_url_root : "" %>' + '/assets/ace/';
var THEME = 'ace/theme/textmate';
@@ -66,10 +66,9 @@ $(function() {
$('#files').append(html);
$('#files li:last select[name*="file_type_id"]').val(getSelectedExecutionEnvironment().file_type_id);
$('#files li:last select').chosen(window.CodeOcean.CHOSEN_OPTIONS);
$('#files li:last select').remove();
$('#files li:last>div:last').removeClass('in').addClass('show')
$('body, html').scrollTo('#add-file');
// if we collapse the file forms by default, we need to click on the new element in order to open it.
// however, this crashes for more files (if we add several ones by clicking the add button more often), since the elements are probably not correctly added to the files list.
//$('#files li:last>div:first>a>div').click();
// initialize the ace editor for the new textarea.
// pass the correct index and the last ace editor under the node files. this is the last one, since we just added it.
@@ -93,7 +92,7 @@ $(function() {
var deleteFile = function(event) {
event.preventDefault();
var fileUrl = $(this).data('file-url');
var fileUrl = $(event.target).data('file-url');
if (confirm('<%= I18n.t('shared.confirm_destroy') %>')) {
var jqxhr = $.ajax({
@@ -139,9 +138,9 @@ $(function() {
var enableBatchUpdate = function() {
$('thead .batch a').on('click', function(event) {
event.preventDefault();
if (!$(this).data('toggled')) {
$(this).data('toggled', true);
$(this).text($(this).data('text'));
if (!$(event.target).data('toggled')) {
$(event.target).data('toggled', true);
$(event.target).text($(event.target).data('text'));
buildCheckboxes();
} else {
performBatchUpdate();
@@ -199,7 +198,7 @@ $(function() {
var observeFileRoleChanges = function() {
$(document).on('change', 'select[name$="[role]"]', function() {
var is_test_file = $(this).val() === 'teacher_defined_test';
var parent = $(this).parents('.panel');
var parent = $(this).parents('.card');
var fields = parent.find('.test-related-fields');
if (is_test_file) {
fields.slideDown();
@@ -262,17 +261,13 @@ $(function() {
jqxhr.fail(ajaxError);
}
if ($.isController('exercises')) {
if ($.isController('exercises') || $.isController('submissions')) {
// ignore tags table since it is in the dom before other tables
if ($('table:not(#tags-table)').isPresent()) {
enableBatchUpdate();
} else if ($('.edit_exercise, .new_exercise').isPresent()) {
execution_environments = $('form').data('execution-environments');
file_types = $('form').data('file-types');
// new MarkdownEditor('#exercise_instructions');
// new MarkdownEditor('#exercise_description')
// todo: add an ace editor for each file
new PagedownEditor('#exercise_description');
enableInlineFileCreation();
inferFileAttributes();

View File

@@ -1,4 +1,4 @@
$(function() {
$(document).on('turbolinks:load', function() {
var grid = $('#tag-grid');
if ($.isController('external_users') && grid.isPresent()) {

View File

@@ -1,4 +1,4 @@
$(function() {
$(document).on('turbolinks:load', function() {
var CHOSEN_OPTIONS = {
allow_single_deselect: true,
disable_search_threshold: 5,
@@ -14,11 +14,11 @@ $(function() {
var alternative_input = parent.find('.alternative-input');
if (alternative_input.attr('disabled')) {
$(this).text($(this).data('text-toggled'));
$(this).text($(event.target).data('text-toggled'));
original_input.attr('disabled', true).hide();
alternative_input.attr('disabled', false).show();
} else {
$(this).text($(this).data('text-initial'));
$(this).text($(event.target).data('text-initial'));
alternative_input.attr('disabled', true).hide();
original_input.attr('disabled', false).show();
}
@@ -26,5 +26,27 @@ $(function() {
});
window.CodeOcean.CHOSEN_OPTIONS = CHOSEN_OPTIONS;
$('select:visible').chosen(CHOSEN_OPTIONS);
chosen_inputs = $('select').filter(function(){
return !$(this).parents('ul').is('#dummies');
});
// enable chosen hook when editing an exercise to update ace code highlighting
if ($.isController('exercises') && $('.edit_exercise, .new_exercise').isPresent()) {
chosen_inputs.filter(function(){
return $(this).attr('id').includes('file_type_id');
}).on('change chosen:ready', function(event, parameter) {
// Set ACE editor mode (for code highlighting) on change of file type and after initialization
editorInstance = $(event.target).closest('.card-body').find('.editor')[0];
selectedFileType = event.target.value;
CodeOceanEditor.updateEditorModeToFileTypeID(editorInstance, selectedFileType);
})
}
chosen_inputs.chosen(CHOSEN_OPTIONS);
});
// Remove some elements before going back to an older site. Otherwise, they might not work.
$(document).on('turbolinks:before-cache', function() {
$('.chosen-container').remove();
$('#wmd-button-row-description').remove();
});

View File

@@ -9,7 +9,7 @@
});
editor.setShowPrintMargin(false);
var session = editor.getSession();
session.setMode('markdown');
session.setMode('ace/mode/markdown');
session.setUseWrapMode(true);
session.setValue($(selector).val());
};

View File

@@ -1,10 +0,0 @@
(function() {
var ACE_FILES_PATH = '/assets/ace/';
window.PagedownEditor = function(selector) {
var converter = Markdown.getSanitizingConverter();
var editor = new Markdown.Editor( converter );
editor.run();
};
})();

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,43 @@
//= require markdown.converter
// markdown.editor is slightly adjusted to work with Bootstrap 4.
// Taken from https://github.com/hughevans/pagedown-bootstrap-rails, V2.1.4
//= require markdown.editor
//= require markdown.sanitizer
//= require markdown.extra
renderPagedown = function() {
$(".wmd-output").each(function (i) {
const converter = new Markdown.Converter();
const content = $(this).html();
return $(this).html(converter.makeHtml(content));
})
};
createPagedownEditor = function( selector, context ) {
if (context == null) { context = 'body'; }
return $(selector, context).each(function(i, input) {
if ($(input).data('is_rendered')) {
return;
}
const attr = $(input).attr('id').split('wmd-input')[1];
const converter = new Markdown.Converter();
Markdown.Extra.init(converter);
const help = {
handler() {
window.open('http://daringfireball.net/projects/markdown/syntax');
return false;
},
title: "<%= I18n.t('components.markdown_editor.help', default: 'Markdown Editing Help') %>"
};
const editor = new Markdown.Editor(converter, attr, help);
editor.run();
$('[data-toggle="tooltip"]').tooltip();
return $(input).data('is_rendered', true);
});
};
$(document).on('turbolinks:load', function() {
renderPagedown();
return createPagedownEditor('.wmd-input');
});

View File

@@ -1,4 +1,4 @@
$(function() {
$(document).on('turbolinks:load', function() {
var ENTER_KEY_CODE = 13;
var clearOutput = function() {

View File

@@ -1,4 +1,4 @@
$(document).ready(function(){
$(document).on('turbolinks:load', function(){
(function vendorTableSorter(){
/*
SortTable

View File

@@ -1,4 +1,4 @@
$(document).ready(function () {
$(document).on('turbolinks:load', function() {
function manageActivityHistory(prefix) {
var containerId = prefix + '-activity-history';
@@ -49,7 +49,7 @@ $(document).ready(function () {
var refreshData = function (callback) {
var params = new URLSearchParams(window.location.search.slice(1));
var jqxhr = $.ajax(prefix + '-activity-history.json', {
var jqxhr = $.ajax('/statistics/graphs/' + prefix + '-activity-history.json', {
dataType: 'json',
data: {from: params.get('from'), to: params.get('to'), interval: params.get('interval')},
method: 'GET'

View File

@@ -1,4 +1,4 @@
$(document).ready(function () {
$(document).on('turbolinks:load', function() {
if ($.isController('statistics') && $('.graph#user-activity').isPresent()) {
function manageGraph(containerId, url, refreshAfter) {
@@ -101,7 +101,7 @@ $(document).ready(function () {
});
}
manageGraph('user-activity', 'graphs/user-activity', 10);
manageGraph('rfc-activity', 'graphs/rfc-activity', 30);
manageGraph('user-activity', '/statistics/graphs/user-activity', 10);
manageGraph('rfc-activity', '/statistics/graphs/rfc-activity', 30);
}
});

View File

@@ -1,34 +1,44 @@
$(function() {
$(document).on('turbolinks:load', function() {
var ACE_FILES_PATH = '/assets/ace/';
var THEME = 'ace/theme/textmate';
var currentSubmission = 0;
var active_file = undefined;
var fileTrees = []
var fileTrees = [];
var editor = undefined;
var fileTypeById = {}
var fileTypeById = {};
var showActiveFile = function() {
var session = editor.getSession();
var fileType = fileTypeById[active_file.file_type_id]
var fileType = fileTypeById[active_file.file_type_id];
session.setMode(fileType.editor_mode);
session.setTabSize(fileType.indent_size);
session.setValue(active_file.content);
session.setUseSoftTabs(true);
session.setUseWrapMode(true);
// The event ready.jstree is fired too early and thus doesn't work.
var selectFileInJsTree = function() {
if (!filetree.hasClass('jstree-loading')) {
filetree.jstree("deselect_all");
filetree.jstree().select_node(active_file.file_id);
} else {
setTimeout(selectFileInJsTree, 250);
}
};
filetree = $(fileTrees[currentSubmission]);
selectFileInJsTree();
// Finally change jstree element to prevent flickering
showFileTree(currentSubmission);
filetree = $(fileTrees[currentSubmission])
filetree.jstree("deselect_all");
filetree.jstree().select_node(active_file.file_id);
};
var initializeFileTree = function() {
$('.files').each(function(index, element) {
fileTree = $(element).jstree($(element).data('entries'));
fileTree.on('click', 'li.jstree-leaf', function() {
var id = parseInt($(this).attr('id'))
var id = parseInt($(this).attr('id'));
_.each(files[currentSubmission], function(file) {
if (file.file_id === id) {
active_file = file;
@@ -42,8 +52,8 @@ $(function() {
var showFileTree = function(index) {
$('.files').hide();
$(fileTrees[index].context).show();
}
$(fileTrees[index]).show();
};
if ($.isController('exercises') && $('#timeline').isPresent()) {
@@ -85,7 +95,7 @@ $(function() {
if (file.name === active_file.name) {
fileIndex = index;
}
})
});
active_file = currentFiles[fileIndex];
showActiveFile();
});
@@ -94,10 +104,10 @@ $(function() {
clearInterval(playInterval);
playInterval = undefined;
playButton.find('span.fa').removeClass('fa-pause').addClass('fa-play')
}
};
playButton.on('click', function(event) {
if (playInterval == undefined) {
if (playInterval === undefined) {
playInterval = setInterval(function() {
if ($.isController('exercises') && $('#timeline').isPresent() && slider.val() < submissions.length - 1) {
slider.val(parseInt(slider.val()) + 1);
@@ -112,7 +122,7 @@ $(function() {
}
});
active_file = files[0][0]
active_file = files[0][0];
initializeFileTree();
showActiveFile();
}

View File

@@ -1,4 +1,4 @@
$(function() {
$(document).on('turbolinks:load', function() {
// http://localhost:3333/exercises/38/statistics good for testing
// originally at--> localhost:3333/exercises/69/statistics
@@ -30,7 +30,7 @@ $(function() {
var studentTime = minutes_array[i];
for (var j = 0; j < studentTime; j++){
if (minutes_count[j] == undefined){
if (minutes_count[j] === undefined){
minutes_count[j] = 0;
} else{
minutes_count[j] += 1;
@@ -173,23 +173,23 @@ $(function() {
//}
// DRAW THE SECOND GRAPH ------------------------------------------------------------------------------
//<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
function draw_bar_graph() {
var group_incrament = 5;
var group_ranges = group_incrament; // just for the start
var number_of_bars = 40;
var group_increment = Math.ceil(maximum_minutes / number_of_bars); // range in minutes
var group_ranges = group_increment; // just for the start
var minutes_array_for_bar = [];
do {
var section_value = 0;
for (var i = 0; i < minutes_array.length; i++) {
if ((minutes_array[i] < group_ranges) && (minutes_array[i] >= (group_ranges - group_incrament))) {
if ((minutes_array[i] < group_ranges) && (minutes_array[i] >= (group_ranges - group_increment))) {
section_value++;
}
}
minutes_array_for_bar.push(section_value);
group_ranges += group_incrament;
group_ranges += group_increment;
}
while (group_ranges < maximum_minutes + group_incrament);
while (group_ranges < maximum_minutes + group_increment);
//console.log(minutes_array_for_bar); // this var used as the bars
//minutes_array_for_bar = [39, 20, 28, 20, 39, 34, 26, 23, 16, 8];
@@ -199,30 +199,30 @@ $(function() {
var width_ratio = .8;
if (getWidth()*width_ratio > 1000){
width_ratio = 1000/getWidth();
}
var height_ratio = .7; // percent of height
var margin = {top: 100, right: 20, bottom: 70, left: 70},//30,50
width = (getWidth() * width_ratio) - margin.left - margin.right,
height = (width * height_ratio) - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var x = d3.scaleBand()
.range([0, width], .1);
var y = d3.scaleLinear()
.range([0,height-(margin.top + margin.bottom)]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
var xAxis = d3.axisBottom(x)
.ticks(10);
var yAxis = d3.svg.axis()
.scale(d3.scaleLinear().domain([0,max_of_array]).range([height,0]))//y
.orient("left")
var yAxis = d3
.axisLeft(d3.scaleLinear().domain([0,max_of_array]).range([height,0]))//y
.ticks(10)
.innerTickSize(-width);
.tickSizeInner(-width);
var tip = d3.tip()
.attr('class', 'd3-tip')
@@ -241,8 +241,8 @@ $(function() {
x.domain(minutes_array_for_bar.map(function (d, i) {
i++;
var high_side = i * group_incrament;
var low_side = high_side - group_incrament;
var high_side = i * group_increment;
var low_side = high_side - group_increment;
return (low_side+"-"+high_side);
}));
@@ -253,7 +253,14 @@ $(function() {
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", function(d) {
return "rotate(-45)"
});
svg.append("g")
.attr("class", "y axis")
@@ -278,7 +285,7 @@ $(function() {
.attr("text-anchor", "middle")
.attr("x", width / 2)
.attr("y", height)
.attr("dy", ((height / 20) + 20) + 'px')
.attr("dy", ((height / 20) + 40) + 'px')
.text("Working Time (Minutes)")
.style('font-size', 14);
@@ -291,10 +298,10 @@ $(function() {
.data(minutes_array_for_bar)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d,i) { var bar_incriment = width/ minutes_array_for_bar.length;
var bar_x = i * bar_incriment;
.attr("x", function(d,i) { var bar_increment = width / minutes_array_for_bar.length;
var bar_x = i * bar_increment;
return (bar_x)})
.attr("width", x.rangeBand())
.attr("width", x.bandwidth())
.attr("y", function(d) { return height - y(d); })
.attr("height", function(d) { return y(d); })
.on('mouseover', tip.show)
@@ -311,7 +318,7 @@ $(function() {
.style('text-decoration', 'underline');
}
// draw_bar_graph();
draw_bar_graph();
}
});