From e2f4991e5450891dc61f9b4d7e47f702a7035226 Mon Sep 17 00:00:00 2001
From: yqbk
Date: Thu, 12 May 2016 17:09:13 +0200
Subject: [PATCH 01/81] change collapsing style
---
app/views/exercises/_file_form.html.slim | 2 +-
app/views/exercises/show.html.slim | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/views/exercises/_file_form.html.slim b/app/views/exercises/_file_form.html.slim
index c737f068..5cdfdc98 100644
--- a/app/views/exercises/_file_form.html.slim
+++ b/app/views/exercises/_file_form.html.slim
@@ -4,7 +4,7 @@ li.panel.panel-default
div.clearfix role="button"
span = f.object.name
a.pull-right data-toggle="collapse" data-parent="#files" href="#collapse#{id}" collapse
- .panel-collapse.collapse.in id="collapse#{id}" role="tabpanel"
+ .panel-collapse.collapse id="collapse#{id}" role="tabpanel"
.panel-body
.clearfix = link_to(t('shared.destroy'), '#', class:'btn btn-warning btn-sm discard-file pull-right')
.form-group
diff --git a/app/views/exercises/show.html.slim b/app/views/exercises/show.html.slim
index fc28272a..ceab96a7 100644
--- a/app/views/exercises/show.html.slim
+++ b/app/views/exercises/show.html.slim
@@ -29,7 +29,7 @@ ul.list-unstyled.panel-group#files
div.clearfix role="button"
span.panel-title = file.name_with_extension
a.pull-right data-toggle="collapse" data-parent="#files" href="#collapse#{file.id}" collapse
- .panel-collapse.collapse.in id="collapse#{file.id}" role="tabpanel"
+ .panel-collapse.collapse id="collapse#{file.id}" role="tabpanel"
.panel-body
- if policy(file).destroy?
.clearfix = link_to(t('shared.destroy'), file, class:'btn btn-warning btn-sm pull-right', data: {confirm: t('shared.confirm_destroy')}, method: :delete)
From a16eb4b15b9ae9846cb258c1ec775f888c0d829a Mon Sep 17 00:00:00 2001
From: yqbk
Date: Thu, 12 May 2016 17:13:30 +0200
Subject: [PATCH 02/81] sorting files alphabetically
---
app/views/exercises/_editor.html.slim | 4 ++--
app/views/exercises/show.html.slim | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/app/views/exercises/_editor.html.slim b/app/views/exercises/_editor.html.slim
index 42b12e42..3340d6ac 100644
--- a/app/views/exercises/_editor.html.slim
+++ b/app/views/exercises/_editor.html.slim
@@ -1,7 +1,7 @@
#editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id
div class=(@exercise.hide_file_tree ? 'hidden col-sm-3' : 'col-sm-3') = render('editor_file_tree', files: @files)
div id='frames' class=(@exercise.hide_file_tree ? 'col-sm-12' : 'col-sm-9')
- - @files.each do |file|
+ - @files.sort{ |a,b| a[:group][:name] <=> b[:group][:name] }.each do |file|
= render('editor_frame', exercise: exercise, file: file)
#autosave-label
= t('exercises.editor.lastsaved')
@@ -38,4 +38,4 @@
= t('exercises.editor.test')
= render('editor_button', data: {:'data-placement' => 'top', :'data-tooltip' => true}, icon: 'fa fa-trophy', id: 'assess', label: t('exercises.editor.score'), title: t('shared.tooltips.shortcut', shortcut: 'ALT + s'))
-= render('shared/modal', id: 'comment-modal', title: t('exercises.implement.comment.request'), template: 'exercises/_request_comment_dialogcontent')
\ No newline at end of file
+= render('shared/modal', id: 'comment-modal', title: t('exercises.implement.comment.request'), template: 'exercises/_request_comment_dialogcontent')
diff --git a/app/views/exercises/show.html.slim b/app/views/exercises/show.html.slim
index ceab96a7..85fb09cb 100644
--- a/app/views/exercises/show.html.slim
+++ b/app/views/exercises/show.html.slim
@@ -23,7 +23,7 @@ h1
h2 = t('activerecord.attributes.exercise.files')
ul.list-unstyled.panel-group#files
- - @exercise.files.each do |file|
+ - @exercise.files.order('name').each do |file|
li.panel.panel-default
.panel-heading role="tab" id="heading"
div.clearfix role="button"
From 10e68915d82d8db4b39aaea790c3beea1848f905 Mon Sep 17 00:00:00 2001
From: yqbk
Date: Thu, 12 May 2016 17:34:30 +0200
Subject: [PATCH 03/81] add key exercise_deadline_passed
---
config/locales/de.yml | 2 ++
config/locales/en.yml | 2 ++
2 files changed, 4 insertions(+)
diff --git a/config/locales/de.yml b/config/locales/de.yml
index e7d78943..30f4f7ef 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -209,8 +209,10 @@ de:
submit: Code zur Bewertung abgeben
test: Testen
timeout: 'Ausführung gestoppt. Ihr Code hat die erlaubte Ausführungszeit von %{permitted_execution_time} Sekunden überschritten.'
+ exercise_deadline_passed: 'Die Abgabefrist für diese Aufgabe ist bereits abgelaufen.'
tooltips:
save: Ihr Code wird automatisch gespeichert, wann immer Sie eine Datei herunterladen, ausführen oder testen. Explizites Speichern ist also selten notwendig.
+ exercise_deadline_passed: 'Die hier erzielten Punkten können nur bis zum Ablauf der Abgabefrist an die E-Learning-Plattform übertragen werden.'
request_for_comments_sent: "Kommentaranfrage gesendet."
editor_file_tree:
file_root: Dateien
diff --git a/config/locales/en.yml b/config/locales/en.yml
index f2470fc8..6cc9dcaf 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -209,8 +209,10 @@ en:
submit: Submit Code For Assessment
test: Test
timeout: 'Execution stopped. Your code exceeded the permitted execution time of %{permitted_execution_time} seconds.'
+ exercise_deadline_passed: 'The deadline for this exercise has already passed'
tooltips:
save: Your code is automatically saved whenever you download, run, or test it. Therefore, explicitly saving is rarely necessary.
+ exercise_deadline_passed: 'The results for this exercise can only be submitted to the e-learning platform before the deadline has passed.'
request_for_comments_sent: "Request for comments sent."
editor_file_tree:
file_root: Files
From e838f5a1b129c32ff94b73778abd84a4bcffec57 Mon Sep 17 00:00:00 2001
From: yqbk
Date: Thu, 12 May 2016 17:35:09 +0200
Subject: [PATCH 04/81] fix submit-button when not active
---
app/views/exercises/implement.html.slim | 3 +++
1 file changed, 3 insertions(+)
diff --git a/app/views/exercises/implement.html.slim b/app/views/exercises/implement.html.slim
index 728492b6..0c5e109b 100644
--- a/app/views/exercises/implement.html.slim
+++ b/app/views/exercises/implement.html.slim
@@ -78,6 +78,9 @@
br
- if session[:lti_parameters].try(:has_key?, 'lis_outcome_service_url')
p.text-center = render('editor_button', classes: 'btn-lg btn-success', data: {:'data-url' => submit_exercise_path(@exercise)}, icon: 'fa fa-send', id: 'submit', label: t('exercises.editor.submit'))
+ - else
+ p.text-center = render('editor_button', classes: 'btn-lg btn-warning-outline', data: {:'data-placement' => 'bottom', :'data-tooltip' => true} , icon: 'fa fa-clock-o', id: 'submit_outdated', label: t('exercises.editor.exercise_deadline_passed'), title: t('exercises.editor.tooltips.exercise_deadline_passed'))
+
- if qa_url
#questions-column
#questions-holder data-url="#{qa_url}/qa/index/#{@exercise.id}/#{@user_id}"
From 5c9a9b8a476a8a1b7fe8d9d1b0e60acb6454d12b Mon Sep 17 00:00:00 2001
From: yqbk
Date: Thu, 12 May 2016 17:53:21 +0200
Subject: [PATCH 05/81] add alert on submit-button click
---
app/assets/javascripts/editor.js.erb | 8 ++++++++
app/views/exercises/_editor.html.slim | 2 +-
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb
index c69551bb..3d9bb5cb 100644
--- a/app/assets/javascripts/editor.js.erb
+++ b/app/assets/javascripts/editor.js.erb
@@ -465,6 +465,7 @@ $(function() {
$('#start').on('click', showWorkspaceTab);
//$('#submit').on('click', confirmSubmission);
$('#submit').on('click', submitCode);
+ $('#submit_outdated').on('click', submitOutdated);
};
var initializeWorkspaceButtons = function() {
@@ -751,6 +752,13 @@ $(function() {
});
};
+ var submitOutdated = function(event) {
+ $.flash.danger({
+ icon: ['fa', 'fa-clock-o'],
+ text: $('#editor').data('message-deadline')
+ });
+ };
+
var sendError = function(message, submission_id) {
showSpinner($('#render'));
var jqxhr = ajax({
diff --git a/app/views/exercises/_editor.html.slim b/app/views/exercises/_editor.html.slim
index 3340d6ac..39ef3bd1 100644
--- a/app/views/exercises/_editor.html.slim
+++ b/app/views/exercises/_editor.html.slim
@@ -1,4 +1,4 @@
-#editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id
+#editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-deadline=t('exercises.editor.deadline_alert') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id
div class=(@exercise.hide_file_tree ? 'hidden col-sm-3' : 'col-sm-3') = render('editor_file_tree', files: @files)
div id='frames' class=(@exercise.hide_file_tree ? 'col-sm-12' : 'col-sm-9')
- @files.sort{ |a,b| a[:group][:name] <=> b[:group][:name] }.each do |file|
From 3189f615353309148ee9a56637ae25e2b635dc0c Mon Sep 17 00:00:00 2001
From: yqbk
Date: Thu, 12 May 2016 18:03:33 +0200
Subject: [PATCH 06/81] no alert on outdated button
---
app/assets/javascripts/editor.js.erb | 8 --------
app/views/exercises/_editor.html.slim | 2 +-
2 files changed, 1 insertion(+), 9 deletions(-)
diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb
index 3d9bb5cb..c69551bb 100644
--- a/app/assets/javascripts/editor.js.erb
+++ b/app/assets/javascripts/editor.js.erb
@@ -465,7 +465,6 @@ $(function() {
$('#start').on('click', showWorkspaceTab);
//$('#submit').on('click', confirmSubmission);
$('#submit').on('click', submitCode);
- $('#submit_outdated').on('click', submitOutdated);
};
var initializeWorkspaceButtons = function() {
@@ -752,13 +751,6 @@ $(function() {
});
};
- var submitOutdated = function(event) {
- $.flash.danger({
- icon: ['fa', 'fa-clock-o'],
- text: $('#editor').data('message-deadline')
- });
- };
-
var sendError = function(message, submission_id) {
showSpinner($('#render'));
var jqxhr = ajax({
diff --git a/app/views/exercises/_editor.html.slim b/app/views/exercises/_editor.html.slim
index 39ef3bd1..b9c41863 100644
--- a/app/views/exercises/_editor.html.slim
+++ b/app/views/exercises/_editor.html.slim
@@ -1,4 +1,4 @@
-#editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-deadline=t('exercises.editor.deadline_alert') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id
+#editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id
div class=(@exercise.hide_file_tree ? 'hidden col-sm-3' : 'col-sm-3') = render('editor_file_tree', files: @files)
div id='frames' class=(@exercise.hide_file_tree ? 'col-sm-12' : 'col-sm-9')
- @files.sort{ |a,b| a[:group][:name] <=> b[:group][:name] }.each do |file|
From d54d1dd3e8b5b8d2b8f1119523f07d046ee85c02 Mon Sep 17 00:00:00 2001
From: yqbk
Date: Thu, 12 May 2016 18:22:17 +0200
Subject: [PATCH 07/81] Score given in percentage
---
app/assets/javascripts/editor.js.erb | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb
index c69551bb..b40b93ec 100644
--- a/app/assets/javascripts/editor.js.erb
+++ b/app/assets/javascripts/editor.js.erb
@@ -706,7 +706,8 @@ $(function() {
var renderScore = function() {
var score = $('#score').data('score');
var maxium_score = $('#score').data('maximum-score');
- $('.score').html((score || '?') + ' / ' + maxium_score);
+ var percentage_score = score / maxium_score * 100
+ $('.score').html((percentage_score || 0) + ' % ');
renderProgressBar(score, maxium_score);
};
From d05ceac7a346bff9f7864a6491efbff6a5e3cab1 Mon Sep 17 00:00:00 2001
From: yqbk
Date: Thu, 12 May 2016 18:30:50 +0200
Subject: [PATCH 08/81] check if score is valid
---
app/assets/javascripts/editor.js.erb | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb
index b40b93ec..1d84361b 100644
--- a/app/assets/javascripts/editor.js.erb
+++ b/app/assets/javascripts/editor.js.erb
@@ -706,8 +706,13 @@ $(function() {
var renderScore = function() {
var score = $('#score').data('score');
var maxium_score = $('#score').data('maximum-score');
- var percentage_score = score / maxium_score * 100
- $('.score').html((percentage_score || 0) + ' % ');
+ if (score >= 0 && score <= maxium_score && maxium_score >0 ) {
+ var percentage_score = score / maxium_score * 100
+ $('.score').html(percentage_score + '%');
+ }
+ else {
+ $('.score').html( 0 + ' % ');
+ }
renderProgressBar(score, maxium_score);
};
From e5b3d33228599f6bf902a260b05eeed5d4404794 Mon Sep 17 00:00:00 2001
From: yqbk
Date: Thu, 12 May 2016 18:34:16 +0200
Subject: [PATCH 09/81] delete spaces
---
app/assets/javascripts/editor.js.erb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb
index 1d84361b..0bb22853 100644
--- a/app/assets/javascripts/editor.js.erb
+++ b/app/assets/javascripts/editor.js.erb
@@ -711,7 +711,7 @@ $(function() {
$('.score').html(percentage_score + '%');
}
else {
- $('.score').html( 0 + ' % ');
+ $('.score').html( 0 + '%');
}
renderProgressBar(score, maxium_score);
};
From a2e1b08730daa61476d0c4cd426446cfe9d83e4f Mon Sep 17 00:00:00 2001
From: yqbk
Date: Thu, 12 May 2016 18:40:42 +0200
Subject: [PATCH 10/81] delete duplicate depleted
---
app/views/exercises/_editor.html.slim | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/views/exercises/_editor.html.slim b/app/views/exercises/_editor.html.slim
index b9c41863..3340d6ac 100644
--- a/app/views/exercises/_editor.html.slim
+++ b/app/views/exercises/_editor.html.slim
@@ -1,4 +1,4 @@
-#editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id
+#editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id
div class=(@exercise.hide_file_tree ? 'hidden col-sm-3' : 'col-sm-3') = render('editor_file_tree', files: @files)
div id='frames' class=(@exercise.hide_file_tree ? 'col-sm-12' : 'col-sm-9')
- @files.sort{ |a,b| a[:group][:name] <=> b[:group][:name] }.each do |file|
From d26d859df1e532fd8519020a1dd08ed6a689c52b Mon Sep 17 00:00:00 2001
From: yqbk
Date: Thu, 12 May 2016 18:45:14 +0200
Subject: [PATCH 11/81] resolve confilts
---
app/views/exercises/_editor.html.slim | 2 +-
app/views/exercises/_file_form.html.slim | 2 +-
app/views/exercises/show.html.slim | 4 ++--
3 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/app/views/exercises/_editor.html.slim b/app/views/exercises/_editor.html.slim
index 3340d6ac..0ce5b73f 100644
--- a/app/views/exercises/_editor.html.slim
+++ b/app/views/exercises/_editor.html.slim
@@ -1,7 +1,7 @@
#editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id
div class=(@exercise.hide_file_tree ? 'hidden col-sm-3' : 'col-sm-3') = render('editor_file_tree', files: @files)
div id='frames' class=(@exercise.hide_file_tree ? 'col-sm-12' : 'col-sm-9')
- - @files.sort{ |a,b| a[:group][:name] <=> b[:group][:name] }.each do |file|
+ - @files.each do |file|
= render('editor_frame', exercise: exercise, file: file)
#autosave-label
= t('exercises.editor.lastsaved')
diff --git a/app/views/exercises/_file_form.html.slim b/app/views/exercises/_file_form.html.slim
index 5cdfdc98..c737f068 100644
--- a/app/views/exercises/_file_form.html.slim
+++ b/app/views/exercises/_file_form.html.slim
@@ -4,7 +4,7 @@ li.panel.panel-default
div.clearfix role="button"
span = f.object.name
a.pull-right data-toggle="collapse" data-parent="#files" href="#collapse#{id}" collapse
- .panel-collapse.collapse id="collapse#{id}" role="tabpanel"
+ .panel-collapse.collapse.in id="collapse#{id}" role="tabpanel"
.panel-body
.clearfix = link_to(t('shared.destroy'), '#', class:'btn btn-warning btn-sm discard-file pull-right')
.form-group
diff --git a/app/views/exercises/show.html.slim b/app/views/exercises/show.html.slim
index 85fb09cb..fc28272a 100644
--- a/app/views/exercises/show.html.slim
+++ b/app/views/exercises/show.html.slim
@@ -23,13 +23,13 @@ h1
h2 = t('activerecord.attributes.exercise.files')
ul.list-unstyled.panel-group#files
- - @exercise.files.order('name').each do |file|
+ - @exercise.files.each do |file|
li.panel.panel-default
.panel-heading role="tab" id="heading"
div.clearfix role="button"
span.panel-title = file.name_with_extension
a.pull-right data-toggle="collapse" data-parent="#files" href="#collapse#{file.id}" collapse
- .panel-collapse.collapse id="collapse#{file.id}" role="tabpanel"
+ .panel-collapse.collapse.in id="collapse#{file.id}" role="tabpanel"
.panel-body
- if policy(file).destroy?
.clearfix = link_to(t('shared.destroy'), file, class:'btn btn-warning btn-sm pull-right', data: {confirm: t('shared.confirm_destroy')}, method: :delete)
From f5aa3cef3ce69f453fbf1fecd9c6ebe6599feb1c Mon Sep 17 00:00:00 2001
From: yqbk
Date: Thu, 12 May 2016 19:03:17 +0200
Subject: [PATCH 12/81] Problem when no files solved
---
app/views/exercises/_editor.html.slim | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/views/exercises/_editor.html.slim b/app/views/exercises/_editor.html.slim
index 3340d6ac..0ce5b73f 100644
--- a/app/views/exercises/_editor.html.slim
+++ b/app/views/exercises/_editor.html.slim
@@ -1,7 +1,7 @@
#editor.row data-exercise-id=exercise.id data-message-depleted=t('exercises.editor.depleted') data-message-timeout=t('exercises.editor.timeout', permitted_execution_time: @exercise.execution_environment.permitted_execution_time) data-errors-url=execution_environment_errors_path(exercise.execution_environment) data-submissions-url=submissions_path data-user-id=@current_user.id
div class=(@exercise.hide_file_tree ? 'hidden col-sm-3' : 'col-sm-3') = render('editor_file_tree', files: @files)
div id='frames' class=(@exercise.hide_file_tree ? 'col-sm-12' : 'col-sm-9')
- - @files.sort{ |a,b| a[:group][:name] <=> b[:group][:name] }.each do |file|
+ - @files.each do |file|
= render('editor_frame', exercise: exercise, file: file)
#autosave-label
= t('exercises.editor.lastsaved')
From 34c9d791f43c83a4b75a7d9ecba28139b0560c29 Mon Sep 17 00:00:00 2001
From: John Geiger
Date: Sun, 29 May 2016 17:30:49 +0200
Subject: [PATCH 13/81] Finishing up graphs. Formatting and adding "Runs"
lines.
---
Gemfile | 2 +-
app/assets/javascripts/exercise_graphs.js | 65 ++---
app/assets/javascripts/working_time_graphs.js | 5 +-
db/schema.rb | 225 ------------------
4 files changed, 43 insertions(+), 254 deletions(-)
delete mode 100644 db/schema.rb
diff --git a/Gemfile b/Gemfile
index 540b11b2..bf089d6c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -37,7 +37,7 @@ gem 'tubesock'
gem 'faye-websocket'
gem 'nokogiri'
gem 'd3-rails'
-gem 'rest-client’
+gem 'rest-client'
group :development do
gem 'better_errors', platform: :ruby
diff --git a/app/assets/javascripts/exercise_graphs.js b/app/assets/javascripts/exercise_graphs.js
index 2d3588c6..f0a9f0fc 100644
--- a/app/assets/javascripts/exercise_graphs.js
+++ b/app/assets/javascripts/exercise_graphs.js
@@ -9,6 +9,7 @@ $(function() {
submissionsScoreAndTimeAssess = [[0,0]];
submissionsScoreAndTimeSubmits = [[0,0]];
+ submissionsScoreAndTimeRuns = [];
var maximumValue = 0;
var wtimes = $('#wtimes').data('working_times'); //.hidden#wtimes data-working_times=ActiveSupport::JSON.encode(working_times_until)
@@ -18,43 +19,38 @@ $(function() {
for (var i = 0;i 0) {
+ submissionArray[1] = workingTime;
+ }
+ if(submission.score>maximumValue){
+ maximumValue = submission.score;
+ }
if(submission.cause == "assess"){
- var workingTime = get_minutes(wtimes[i]);
- var submissionArray = [submission.score, 0];
-
- if (workingTime > 0) {
- submissionArray[1] = workingTime;
- }
-
- if(submission.score>maximumValue){
- maximumValue = submission.score;
- }
submissionsScoreAndTimeAssess.push(submissionArray);
} else if(submission.cause == "submit"){
- var workingTime = get_minutes(wtimes[i]);
- var submissionArray = [submission.score, 0];
-
- if (workingTime > 0) {
- submissionArray[1] = workingTime;
- }
-
- if(submission.score>maximumValue){
- maximumValue = submission.score;
- }
submissionsScoreAndTimeSubmits.push(submissionArray);
+ } else if(submission.cause == "run"){
+ submissionsScoreAndTimeRuns.push(submissionArray[1]);
}
}
// console.log(submissionsScoreAndTimeAssess.length);
// console.log(submissionsScoreAndTimeSubmits);
+ // console.log(submissionsScoreAndTimeRuns);
function get_minutes (time_stamp) {
try {
hours = time_stamp.split(":")[0];
minutes = time_stamp.split(":")[1];
seconds = time_stamp.split(":")[2];
-
- minutes = parseFloat(hours * 60) + parseInt(minutes);
+ seconds /= 60;
+ minutes = parseFloat(hours * 60) + parseInt(minutes) + seconds;
if (minutes > 0){
return minutes;
} else{
@@ -82,6 +78,9 @@ $(function() {
function graph_assesses() {
// MAKE THE GRAPH
var width_ratio = .8;
+ if (width_ratio > 1000){
+ width_ratio = 1000;
+ }
var height_ratio = .7; // percent of height
var margin = {top: 100, right: 20, bottom: 70, left: 70},//30,50
@@ -221,10 +220,21 @@ $(function() {
.attr("cx", function(d) { return x(d[1]); })
.attr("cy", function(d) { return y(d[0]); });
+ for (var i = 0; i < submissionsScoreAndTimeRuns.length; i++) {
+ svg.append("line")
+ .attr("stroke", "red")
+ .attr("stroke-width", 1)
+ .attr("fill", "none")// end new
+ .attr("y1", y(0))
+ .attr("y2", 0)
+ .attr("x1", x(submissionsScoreAndTimeRuns[i]))
+ .attr("x2", x(submissionsScoreAndTimeRuns[i]));
+ }
var color_hash = { 0 : ["Submissions", "blue"],
- 1 : ["Assesses", "orange"]
- }
+ 1 : ["Assesses", "orange"],
+ 2 : ["Runs", "red"]
+ };
// add legend
var legend = svg.append("g")
@@ -234,7 +244,8 @@ $(function() {
.attr("height", 100)
.attr("width", 100);
- var dataset = [submissionsScoreAndTimeSubmits,submissionsScoreAndTimeAssess];
+ var dataset = [submissionsScoreAndTimeSubmits,submissionsScoreAndTimeAssess, submissionsScoreAndTimeRuns];
+ var yOffset = -70;
legend.selectAll('g').data(dataset)
.enter()
@@ -243,14 +254,14 @@ $(function() {
var g = d3.select(this);
g.append("rect")
.attr("x", 20)
- .attr("y", i*25 + 8)
+ .attr("y", i*25 + yOffset)// + 8
.attr("width", 10)
.attr("height", 10)
.style("fill", color_hash[String(i)][1]);
g.append("text")
.attr("x", 40)
- .attr("y", i * 25 + 18)
+ .attr("y", i * 25 + yOffset + 10)// + 18
.attr("height",30)
.attr("width",100)
.style("fill", color_hash[String(i)][1])
diff --git a/app/assets/javascripts/working_time_graphs.js b/app/assets/javascripts/working_time_graphs.js
index 315d2c09..4b6db432 100644
--- a/app/assets/javascripts/working_time_graphs.js
+++ b/app/assets/javascripts/working_time_graphs.js
@@ -4,7 +4,7 @@ $(function() {
if ($.isController('exercises') && $('.graph-functions').isPresent()) {
var working_times = $('#data').data('working-time');
-
+
function get_minutes (time_stamp){
try{
hours = time_stamp.split(":")[0];
@@ -67,6 +67,9 @@ $(function() {
// DRAW THE LINE GRAPH ------------------------------------------------------------------------------
function draw_line_graph() {
var width_ratio = .8;
+ if (width_ratio > 1000){
+ width_ratio = 1000;
+ }
var height_ratio = .7; // percent of height
// currently sets as percentage of window width, however, unfortunately
diff --git a/db/schema.rb b/db/schema.rb
deleted file mode 100644
index bcf1a675..00000000
--- a/db/schema.rb
+++ /dev/null
@@ -1,225 +0,0 @@
-# encoding: UTF-8
-# This file is auto-generated from the current state of the database. Instead
-# of editing this file, please use the migrations feature of Active Record to
-# incrementally modify your database, and then regenerate this schema definition.
-#
-# Note that this schema.rb definition is the authoritative source for your
-# database schema. If you need to create the application database on another
-# system, you should be using db:schema:load, not running all the migrations
-# from scratch. The latter is a flawed and unsustainable approach (the more migrations
-# you'll amass, the slower it'll run and the greater likelihood for issues).
-#
-# It's strongly recommended that you check this file into your version control system.
-
-ActiveRecord::Schema.define(version: 20160510145341) do
-
- # These are extensions that must be enabled in order to support this database
- enable_extension "plpgsql"
-
- create_table "code_harbor_links", force: true do |t|
- t.string "oauth2token"
- t.datetime "created_at"
- t.datetime "updated_at"
- t.integer "user_id"
- end
-
- add_index "code_harbor_links", ["user_id"], name: "index_code_harbor_links_on_user_id", using: :btree
-
- create_table "comments", force: true do |t|
- t.integer "user_id"
- t.integer "file_id"
- t.string "user_type"
- t.integer "row"
- t.integer "column"
- t.string "text"
- t.datetime "created_at"
- t.datetime "updated_at"
- end
-
- add_index "comments", ["file_id"], name: "index_comments_on_file_id", using: :btree
- add_index "comments", ["user_id"], name: "index_comments_on_user_id", using: :btree
-
- create_table "consumers", force: true do |t|
- t.string "name"
- t.datetime "created_at"
- t.datetime "updated_at"
- t.string "oauth_key"
- t.string "oauth_secret"
- end
-
- create_table "errors", force: true do |t|
- t.integer "execution_environment_id"
- t.text "message"
- t.datetime "created_at"
- t.datetime "updated_at"
- t.integer "submission_id"
- end
-
- add_index "errors", ["submission_id"], name: "index_errors_on_submission_id", using: :btree
-
- create_table "execution_environments", force: true do |t|
- t.string "docker_image"
- t.string "name"
- t.datetime "created_at"
- t.datetime "updated_at"
- t.string "run_command"
- t.string "test_command"
- t.string "testing_framework"
- t.text "help"
- t.string "exposed_ports"
- t.integer "permitted_execution_time"
- t.integer "user_id"
- t.string "user_type"
- t.integer "pool_size"
- t.integer "file_type_id"
- t.integer "memory_limit"
- t.boolean "network_enabled"
- end
-
- create_table "exercises", force: true do |t|
- t.text "description"
- t.integer "execution_environment_id"
- t.string "title"
- t.datetime "created_at"
- t.datetime "updated_at"
- t.integer "user_id"
- t.text "instructions"
- t.boolean "public"
- t.string "user_type"
- t.string "token"
- t.integer "team_id"
- t.boolean "hide_file_tree"
- t.boolean "allow_file_creation"
- end
-
- add_index "exercises", ["execution_environment_id"], name: "test3", using: :btree
-
- create_table "external_users", force: true do |t|
- t.integer "consumer_id"
- t.string "email"
- t.string "external_id"
- t.string "name"
- t.datetime "created_at"
- t.datetime "updated_at"
- end
-
- create_table "file_types", force: true do |t|
- t.string "editor_mode"
- t.string "file_extension"
- t.integer "indent_size"
- t.string "name"
- t.integer "user_id"
- t.datetime "created_at"
- t.datetime "updated_at"
- t.boolean "executable"
- t.boolean "renderable"
- t.string "user_type"
- t.boolean "binary"
- end
-
- create_table "files", force: true do |t|
- t.text "content"
- t.integer "context_id"
- t.string "context_type"
- t.integer "file_id"
- t.integer "file_type_id"
- t.boolean "hidden"
- t.string "name"
- t.boolean "read_only"
- t.datetime "created_at"
- t.datetime "updated_at"
- t.string "native_file"
- t.string "role"
- t.string "hashed_content"
- t.string "feedback_message"
- t.float "weight"
- t.string "path"
- end
-
- add_index "files", ["context_id", "context_type"], name: "index_files_on_context_id_and_context_type", using: :btree
-
- create_table "hints", force: true do |t|
- t.integer "execution_environment_id"
- t.string "locale"
- t.text "message"
- t.string "name"
- t.string "regular_expression"
- t.datetime "created_at"
- t.datetime "updated_at"
- end
-
- create_table "internal_users", force: true do |t|
- t.integer "consumer_id"
- t.string "email"
- t.string "name"
- t.string "role"
- t.datetime "created_at"
- t.datetime "updated_at"
- t.string "crypted_password"
- t.string "salt"
- t.integer "failed_logins_count", default: 0
- t.datetime "lock_expires_at"
- t.string "unlock_token"
- t.string "remember_me_token"
- t.datetime "remember_me_token_expires_at"
- t.string "reset_password_token"
- t.datetime "reset_password_token_expires_at"
- t.datetime "reset_password_email_sent_at"
- t.string "activation_state"
- t.string "activation_token"
- t.datetime "activation_token_expires_at"
- end
-
- add_index "internal_users", ["activation_token"], name: "index_internal_users_on_activation_token", using: :btree
- add_index "internal_users", ["email"], name: "index_internal_users_on_email", unique: true, using: :btree
- add_index "internal_users", ["remember_me_token"], name: "index_internal_users_on_remember_me_token", using: :btree
- add_index "internal_users", ["reset_password_token"], name: "index_internal_users_on_reset_password_token", using: :btree
-
- create_table "internal_users_teams", force: true do |t|
- t.integer "internal_user_id"
- t.integer "team_id"
- end
-
- add_index "internal_users_teams", ["internal_user_id"], name: "index_internal_users_teams_on_internal_user_id", using: :btree
- add_index "internal_users_teams", ["team_id"], name: "index_internal_users_teams_on_team_id", using: :btree
-
- create_table "request_for_comments", force: true do |t|
- t.integer "user_id", null: false
- t.integer "exercise_id", null: false
- t.integer "file_id", null: false
- t.datetime "requested_at"
- t.datetime "created_at"
- t.datetime "updated_at"
- t.string "user_type"
- t.text "question"
- end
-
- create_table "submissions", force: true do |t|
- t.integer "exercise_id"
- t.float "score"
- t.integer "user_id"
- t.datetime "created_at"
- t.datetime "updated_at"
- t.string "cause"
- t.string "user_type"
- end
-
- add_index "submissions", ["exercise_id"], name: "test1", where: "((user_type)::text = 'ExternalUser'::text)", using: :btree
- add_index "submissions", ["exercise_id"], name: "test2", using: :btree
-
- create_table "teams", force: true do |t|
- t.string "name"
- t.datetime "created_at"
- t.datetime "updated_at"
- end
-
- create_table "testruns", force: true do |t|
- t.boolean "passed"
- t.text "output"
- t.integer "file_id"
- t.integer "submission_id"
- t.datetime "created_at"
- t.datetime "updated_at"
- end
-
-end
From b6cd797772191fc170ee5c224add0829bb3ceda6 Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Tue, 31 May 2016 11:17:11 +0200
Subject: [PATCH 14/81] Show displayname instead of username in
request_for_comment
---
app/views/request_for_comments/show.html.erb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/views/request_for_comments/show.html.erb b/app/views/request_for_comments/show.html.erb
index ab53ebd0..e4dc7f06 100644
--- a/app/views/request_for_comments/show.html.erb
+++ b/app/views/request_for_comments/show.html.erb
@@ -12,7 +12,7 @@
limit 1").first['id'].to_i
submission = Submission.find(submission_id)
%>
- <%= user %> | <%= @request_for_comment.requested_at %>
+ <%= user.displayname %> | <%= @request_for_comment.requested_at %>
<% if @request_for_comment.question and not @request_for_comment.question == '' %>
From 8158d60d307d348095f16933b91ba769938aaa61 Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Wed, 1 Jun 2016 11:30:42 +0200
Subject: [PATCH 15/81] also write "parsable json" to the frontend console if
it does not have a valid command set (solves the issue when just printing an
array in java, it is not shown anywhere).
---
app/controllers/submissions_controller.rb | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb
index 1fec0b1b..4f9d6a5b 100644
--- a/app/controllers/submissions_controller.rb
+++ b/app/controllers/submissions_controller.rb
@@ -174,8 +174,14 @@ class SubmissionsController < ApplicationController
def parse_message(message, output_stream, socket, recursive = true)
begin
parsed = JSON.parse(message)
- socket.send_data message
- Rails.logger.info('parse_message sent: ' + message)
+ if(parsed.class == Hash && parsed.key?('cmd'))
+ socket.send_data message
+ Rails.logger.info('parse_message sent: ' + message)
+ else
+ parsed = {'cmd'=>'write','stream'=>output_stream,'data'=>message}
+ socket.send_data JSON.dump(parsed)
+ Rails.logger.info('parse_message sent: ' + JSON.dump(parsed))
+ end
rescue JSON::ParserError => e
# Check wether the message contains multiple lines, if true try to parse each line
if ((recursive == true) && (message.include? "\n"))
From 2ff04cf59df90dd0c3432268b8de784a6ee5d50c Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Thu, 2 Jun 2016 15:27:36 +0200
Subject: [PATCH 16/81] fixed scaling of graphs
---
app/assets/javascripts/exercise_graphs.js | 4 ++--
app/assets/javascripts/working_time_graphs.js | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/app/assets/javascripts/exercise_graphs.js b/app/assets/javascripts/exercise_graphs.js
index f0a9f0fc..8b11f668 100644
--- a/app/assets/javascripts/exercise_graphs.js
+++ b/app/assets/javascripts/exercise_graphs.js
@@ -78,8 +78,8 @@ $(function() {
function graph_assesses() {
// MAKE THE GRAPH
var width_ratio = .8;
- if (width_ratio > 1000){
- width_ratio = 1000;
+ if (getWidth()*width_ratio > 1000){
+ width_ratio = 1000/getWidth();
}
var height_ratio = .7; // percent of height
diff --git a/app/assets/javascripts/working_time_graphs.js b/app/assets/javascripts/working_time_graphs.js
index 4b6db432..181b3799 100644
--- a/app/assets/javascripts/working_time_graphs.js
+++ b/app/assets/javascripts/working_time_graphs.js
@@ -67,8 +67,8 @@ $(function() {
// DRAW THE LINE GRAPH ------------------------------------------------------------------------------
function draw_line_graph() {
var width_ratio = .8;
- if (width_ratio > 1000){
- width_ratio = 1000;
+ if (getWidth()*width_ratio > 1000){
+ width_ratio = 1000/getWidth();
}
var height_ratio = .7; // percent of height
From 5ba980b31612c092afa8ac98d7470e57705a7636 Mon Sep 17 00:00:00 2001
From: John Geiger
Date: Thu, 2 Jun 2016 15:30:18 +0200
Subject: [PATCH 17/81] Fix x-axis domain problem
---
app/assets/javascripts/exercise_graphs.js | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/app/assets/javascripts/exercise_graphs.js b/app/assets/javascripts/exercise_graphs.js
index 8b11f668..efde486d 100644
--- a/app/assets/javascripts/exercise_graphs.js
+++ b/app/assets/javascripts/exercise_graphs.js
@@ -130,8 +130,17 @@ $(function() {
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
+ var largestSubmittedTimeStamp = submissions[submissions_length-1];
+ var largestArrayForRange;
+ if(largestSubmittedTimeStamp.cause == "assess"){
+ largestArrayForRange = submissionsScoreAndTimeAssess;
+ } else if(largestSubmittedTimeStamp.cause == "submit"){
+ largestArrayForRange = submissionsScoreAndTimeSubmits;
+ } else if(largestSubmittedTimeStamp.cause == "run"){
+ largestArrayForRange = submissionsScoreAndTimeRuns;
+ }
- x.domain(d3.extent(submissionsScoreAndTimeAssess, function (d) {
+ x.domain(d3.extent(largestArrayForRange, function (d) {
// console.log(d[1]);
return (d[1]);
}));
From 3c8bd90e2b03fec1d904ccefb3e0ce89346f13e2 Mon Sep 17 00:00:00 2001
From: John Geiger
Date: Thu, 2 Jun 2016 15:40:18 +0200
Subject: [PATCH 18/81] fix indexing for x axis
---
app/assets/javascripts/exercise_graphs.js | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/app/assets/javascripts/exercise_graphs.js b/app/assets/javascripts/exercise_graphs.js
index efde486d..8e6263bf 100644
--- a/app/assets/javascripts/exercise_graphs.js
+++ b/app/assets/javascripts/exercise_graphs.js
@@ -131,18 +131,23 @@ $(function() {
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var largestSubmittedTimeStamp = submissions[submissions_length-1];
+ var indexForTime;
var largestArrayForRange;
if(largestSubmittedTimeStamp.cause == "assess"){
- largestArrayForRange = submissionsScoreAndTimeAssess;
+ largestArrayForRange = submissionsScoreAndTimeAssess[1];
+ indexForTime = 1;
} else if(largestSubmittedTimeStamp.cause == "submit"){
- largestArrayForRange = submissionsScoreAndTimeSubmits;
+ largestArrayForRange = submissionsScoreAndTimeSubmits[1];
+ indexForTime = 1;
} else if(largestSubmittedTimeStamp.cause == "run"){
- largestArrayForRange = submissionsScoreAndTimeRuns;
+ largestArrayForRange = submissionsScoreAndTimeRuns[0];
+ indexForTime = 0;
+
}
x.domain(d3.extent(largestArrayForRange, function (d) {
// console.log(d[1]);
- return (d[1]);
+ return (d[indexForTime]);
}));
y.domain(d3.extent(submissionsScoreAndTimeAssess, function (d) {
// console.log(d[0]);
From cd005483ab4814be176f53791f326853c0ee224e Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Thu, 2 Jun 2016 16:34:13 +0200
Subject: [PATCH 19/81] removed incorrect array accesses.
---
app/assets/javascripts/exercise_graphs.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/app/assets/javascripts/exercise_graphs.js b/app/assets/javascripts/exercise_graphs.js
index 8e6263bf..8e8e15db 100644
--- a/app/assets/javascripts/exercise_graphs.js
+++ b/app/assets/javascripts/exercise_graphs.js
@@ -134,13 +134,13 @@ $(function() {
var indexForTime;
var largestArrayForRange;
if(largestSubmittedTimeStamp.cause == "assess"){
- largestArrayForRange = submissionsScoreAndTimeAssess[1];
+ largestArrayForRange = submissionsScoreAndTimeAssess;
indexForTime = 1;
} else if(largestSubmittedTimeStamp.cause == "submit"){
- largestArrayForRange = submissionsScoreAndTimeSubmits[1];
+ largestArrayForRange = submissionsScoreAndTimeSubmits;
indexForTime = 1;
} else if(largestSubmittedTimeStamp.cause == "run"){
- largestArrayForRange = submissionsScoreAndTimeRuns[0];
+ largestArrayForRange = submissionsScoreAndTimeRuns;
indexForTime = 0;
}
From c8b21dd7ea446987d985c9936773812aecf7a6fb Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Fri, 3 Jun 2016 15:26:24 +0200
Subject: [PATCH 20/81] first steps for new mails on comments.
---
app/mailers/user_mailer.rb | 5 +++++
app/views/user_mailer/got_new_comment.slim | 1 +
2 files changed, 6 insertions(+)
create mode 100644 app/views/user_mailer/got_new_comment.slim
diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb
index 4b3c71f4..8cb5eed1 100644
--- a/app/mailers/user_mailer.rb
+++ b/app/mailers/user_mailer.rb
@@ -11,4 +11,9 @@ class UserMailer < ActionMailer::Base
@reset_password_url = reset_password_internal_user_url(user, token: user.reset_password_token)
mail(subject: t('mailers.user_mailer.reset_password.subject'), to: user.email)
end
+
+ def got_new_comment(comment, user, commenting_user)
+ @commenting_user = commenting_user
+ mail(subject: t('mailers.user_mailer.got_new_comment.subject'), to: user.email)
+ end
end
diff --git a/app/views/user_mailer/got_new_comment.slim b/app/views/user_mailer/got_new_comment.slim
new file mode 100644
index 00000000..3b8afa5b
--- /dev/null
+++ b/app/views/user_mailer/got_new_comment.slim
@@ -0,0 +1 @@
+== t('mailers.user_mailer.activation_needed.body', link: link_to(@activation_url, @activation_url))
From a75227c8f7ffcaab447ca5c4b69aaae887a6eafe Mon Sep 17 00:00:00 2001
From: Maximilian Grundke
Date: Wed, 8 Jun 2016 11:49:34 +0200
Subject: [PATCH 21/81] Don't call author policy if author is missing
---
app/views/exercises/index.html.slim | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/views/exercises/index.html.slim b/app/views/exercises/index.html.slim
index 97847f1f..ae018e82 100644
--- a/app/views/exercises/index.html.slim
+++ b/app/views/exercises/index.html.slim
@@ -27,7 +27,7 @@ h1 = Exercise.model_name.human(count: 2)
- @exercises.each do |exercise|
tr data-id=exercise.id
td = exercise.title
- td = link_to_if(policy(exercise.author).show?, exercise.author, exercise.author)
+ td = link_to_if(exercise.author && policy(exercise.author).show?, exercise.author, exercise.author)
td = link_to_if(exercise.execution_environment && policy(exercise.execution_environment).show?, exercise.execution_environment, exercise.execution_environment)
td = exercise.files.teacher_defined_tests.count
td = exercise.maximum_score
From 52ba35d0e4d20f4a41ad7d64a7efde1dcdee770c Mon Sep 17 00:00:00 2001
From: John Geiger
Date: Wed, 8 Jun 2016 13:55:09 +0200
Subject: [PATCH 22/81] fixed graph sizing
---
app/assets/javascripts/exercise_graphs.js | 38 ++++++++++++++++++-----
1 file changed, 30 insertions(+), 8 deletions(-)
diff --git a/app/assets/javascripts/exercise_graphs.js b/app/assets/javascripts/exercise_graphs.js
index 8e8e15db..f5640788 100644
--- a/app/assets/javascripts/exercise_graphs.js
+++ b/app/assets/javascripts/exercise_graphs.js
@@ -10,6 +10,8 @@ $(function() {
submissionsScoreAndTimeAssess = [[0,0]];
submissionsScoreAndTimeSubmits = [[0,0]];
submissionsScoreAndTimeRuns = [];
+ submissionsSaves = [];
+ submissionsAutosaves = [];
var maximumValue = 0;
var wtimes = $('#wtimes').data('working_times'); //.hidden#wtimes data-working_times=ActiveSupport::JSON.encode(working_times_until)
@@ -38,6 +40,10 @@ $(function() {
submissionsScoreAndTimeSubmits.push(submissionArray);
} else if(submission.cause == "run"){
submissionsScoreAndTimeRuns.push(submissionArray[1]);
+ } else if(submission.cause == "autosave"){
+ submissionsAutosaves.push(submissionArray[1]);
+ } else if(submission.cause == "save"){
+ submissionsSaves.push(submissionArray[1]);
}
}
// console.log(submissionsScoreAndTimeAssess.length);
@@ -131,8 +137,8 @@ $(function() {
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var largestSubmittedTimeStamp = submissions[submissions_length-1];
- var indexForTime;
var largestArrayForRange;
+
if(largestSubmittedTimeStamp.cause == "assess"){
largestArrayForRange = submissionsScoreAndTimeAssess;
indexForTime = 1;
@@ -142,17 +148,33 @@ $(function() {
} else if(largestSubmittedTimeStamp.cause == "run"){
largestArrayForRange = submissionsScoreAndTimeRuns;
indexForTime = 0;
-
+ x.domain([0,largestArrayForRange[largestArrayForRange.length - 1][1]]).clamp(true);
+ } else if(largestSubmittedTimeStamp.cause == "submit"){
+ largestArrayForRange = submissionsScoreAndTimeSubmits;
+ x.domain([0,largestArrayForRange[largestArrayForRange.length - 1][1]]).clamp(true);
+ } else if(largestSubmittedTimeStamp.cause == "run"){
+ largestArrayForRange = submissionsScoreAndTimeRuns;
+ x.domain([0,largestArrayForRange[largestArrayForRange.length - 1][1]]).clamp(true);
+ } else if(largestSubmittedTimeStamp.cause == "autosave"){
+ largestArrayForRange = submissionsAutosaves;
+ x.domain([0,largestArrayForRange[largestArrayForRange.length - 1]]).clamp(true);
+ } else if(largestSubmittedTimeStamp.cause == "save"){
+ largestArrayForRange = submissionsSaves;
+ x.domain([0,largestArrayForRange[largestArrayForRange.length - 1]]).clamp(true);
}
- x.domain(d3.extent(largestArrayForRange, function (d) {
- // console.log(d[1]);
- return (d[indexForTime]);
- }));
- y.domain(d3.extent(submissionsScoreAndTimeAssess, function (d) {
+ // x.domain(d3.extent(largestArrayForRange, function (d) {
+ // // console.log(d[1]);
+ // return (d[indexForTime]);
+ // }));
+
+ // take maximum value between assesses and submits
+ var yDomain = submissionsScoreAndTimeAssess.concat(submissionsScoreAndTimeSubmits);
+ y.domain(d3.extent(yDomain, function (d) {
// console.log(d[0]);
return (d[0]);
}));
+ // y.domain([0,2]).clamp(true);
svg.append("g") //x axis
.attr("class", "x axis")
@@ -298,7 +320,7 @@ $(function() {
try{
graph_assesses();
} catch(err){
- // not enough data
+ alert("could not draw the graph");
}
}
From 9e5297c1de6b0bc08b9e1d1f4507f69c5ac693a9 Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Wed, 8 Jun 2016 14:05:13 +0200
Subject: [PATCH 23/81] re-add schema.rb
---
db/schema.rb | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 220 insertions(+)
create mode 100644 db/schema.rb
diff --git a/db/schema.rb b/db/schema.rb
new file mode 100644
index 00000000..f519dfe1
--- /dev/null
+++ b/db/schema.rb
@@ -0,0 +1,220 @@
+# encoding: UTF-8
+# This file is auto-generated from the current state of the database. Instead
+# of editing this file, please use the migrations feature of Active Record to
+# incrementally modify your database, and then regenerate this schema definition.
+#
+# Note that this schema.rb definition is the authoritative source for your
+# database schema. If you need to create the application database on another
+# system, you should be using db:schema:load, not running all the migrations
+# from scratch. The latter is a flawed and unsustainable approach (the more migrations
+# you'll amass, the slower it'll run and the greater likelihood for issues).
+#
+# It's strongly recommended that you check this file into your version control system.
+
+ActiveRecord::Schema.define(version: 20160512131539) do
+
+ # These are extensions that must be enabled in order to support this database
+ enable_extension "plpgsql"
+
+ create_table "code_harbor_links", force: true do |t|
+ t.string "oauth2token"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.integer "user_id"
+ end
+
+ add_index "code_harbor_links", ["user_id"], name: "index_code_harbor_links_on_user_id", using: :btree
+
+ create_table "comments", force: true do |t|
+ t.integer "user_id"
+ t.integer "file_id"
+ t.string "user_type"
+ t.integer "row"
+ t.integer "column"
+ t.text "text"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
+ add_index "comments", ["file_id"], name: "index_comments_on_file_id", using: :btree
+ add_index "comments", ["user_id"], name: "index_comments_on_user_id", using: :btree
+
+ create_table "consumers", force: true do |t|
+ t.string "name"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.string "oauth_key"
+ t.string "oauth_secret"
+ end
+
+ create_table "errors", force: true do |t|
+ t.integer "execution_environment_id"
+ t.text "message"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.integer "submission_id"
+ end
+
+ add_index "errors", ["submission_id"], name: "index_errors_on_submission_id", using: :btree
+
+ create_table "execution_environments", force: true do |t|
+ t.string "docker_image"
+ t.string "name"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.string "run_command"
+ t.string "test_command"
+ t.string "testing_framework"
+ t.text "help"
+ t.string "exposed_ports"
+ t.integer "permitted_execution_time"
+ t.integer "user_id"
+ t.string "user_type"
+ t.integer "pool_size"
+ t.integer "file_type_id"
+ t.integer "memory_limit"
+ t.boolean "network_enabled"
+ end
+
+ create_table "exercises", force: true do |t|
+ t.text "description"
+ t.integer "execution_environment_id"
+ t.string "title"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.integer "user_id"
+ t.text "instructions"
+ t.boolean "public"
+ t.string "user_type"
+ t.string "token"
+ t.integer "team_id"
+ t.boolean "hide_file_tree"
+ t.boolean "allow_file_creation"
+ end
+
+ create_table "external_users", force: true do |t|
+ t.integer "consumer_id"
+ t.string "email"
+ t.string "external_id"
+ t.string "name"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
+ create_table "file_types", force: true do |t|
+ t.string "editor_mode"
+ t.string "file_extension"
+ t.integer "indent_size"
+ t.string "name"
+ t.integer "user_id"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.boolean "executable"
+ t.boolean "renderable"
+ t.string "user_type"
+ t.boolean "binary"
+ end
+
+ create_table "files", force: true do |t|
+ t.text "content"
+ t.integer "context_id"
+ t.string "context_type"
+ t.integer "file_id"
+ t.integer "file_type_id"
+ t.boolean "hidden"
+ t.string "name"
+ t.boolean "read_only"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.string "native_file"
+ t.string "role"
+ t.string "hashed_content"
+ t.string "feedback_message"
+ t.float "weight"
+ t.string "path"
+ end
+
+ add_index "files", ["context_id", "context_type"], name: "index_files_on_context_id_and_context_type", using: :btree
+
+ create_table "hints", force: true do |t|
+ t.integer "execution_environment_id"
+ t.string "locale"
+ t.text "message"
+ t.string "name"
+ t.string "regular_expression"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
+ create_table "internal_users", force: true do |t|
+ t.integer "consumer_id"
+ t.string "email"
+ t.string "name"
+ t.string "role"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.string "crypted_password"
+ t.string "salt"
+ t.integer "failed_logins_count", default: 0
+ t.datetime "lock_expires_at"
+ t.string "unlock_token"
+ t.string "remember_me_token"
+ t.datetime "remember_me_token_expires_at"
+ t.string "reset_password_token"
+ t.datetime "reset_password_token_expires_at"
+ t.datetime "reset_password_email_sent_at"
+ t.string "activation_state"
+ t.string "activation_token"
+ t.datetime "activation_token_expires_at"
+ end
+
+ add_index "internal_users", ["activation_token"], name: "index_internal_users_on_activation_token", using: :btree
+ add_index "internal_users", ["email"], name: "index_internal_users_on_email", unique: true, using: :btree
+ add_index "internal_users", ["remember_me_token"], name: "index_internal_users_on_remember_me_token", using: :btree
+ add_index "internal_users", ["reset_password_token"], name: "index_internal_users_on_reset_password_token", using: :btree
+
+ create_table "internal_users_teams", force: true do |t|
+ t.integer "internal_user_id"
+ t.integer "team_id"
+ end
+
+ add_index "internal_users_teams", ["internal_user_id"], name: "index_internal_users_teams_on_internal_user_id", using: :btree
+ add_index "internal_users_teams", ["team_id"], name: "index_internal_users_teams_on_team_id", using: :btree
+
+ create_table "request_for_comments", force: true do |t|
+ t.integer "user_id", null: false
+ t.integer "exercise_id", null: false
+ t.integer "file_id", null: false
+ t.datetime "requested_at"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.string "user_type"
+ t.text "question"
+ end
+
+ create_table "submissions", force: true do |t|
+ t.integer "exercise_id"
+ t.float "score"
+ t.integer "user_id"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.string "cause"
+ t.string "user_type"
+ end
+
+ create_table "teams", force: true do |t|
+ t.string "name"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
+ create_table "testruns", force: true do |t|
+ t.boolean "passed"
+ t.text "output"
+ t.integer "file_id"
+ t.integer "submission_id"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
+end
\ No newline at end of file
From 81fe1f1f14a5c2e00ce45968c2e4c4f920d92cc2 Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Wed, 8 Jun 2016 14:07:34 +0200
Subject: [PATCH 24/81] fix end-line of schema.rb
---
db/schema.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/db/schema.rb b/db/schema.rb
index f519dfe1..104a1469 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -217,4 +217,4 @@ ActiveRecord::Schema.define(version: 20160512131539) do
t.datetime "updated_at"
end
-end
\ No newline at end of file
+end
From 1cd879bcb6560ed43f35a366281f40042d6c1370 Mon Sep 17 00:00:00 2001
From: Maximilian Grundke
Date: Thu, 9 Jun 2016 22:38:19 +0200
Subject: [PATCH 25/81] Scaffold file templates
---
.../javascripts/file_templates.js.coffee | 3 +
.../stylesheets/file_templates.css.scss | 3 +
app/controllers/file_templates_controller.rb | 86 +++++++++++++++++++
app/models/file_template.rb | 10 +++
app/models/file_type.rb | 1 +
app/policies/file_template_policy.rb | 7 ++
app/views/file_templates/_form.html.slim | 12 +++
app/views/file_templates/edit.html.slim | 3 +
app/views/file_templates/index.html.slim | 20 +++++
app/views/file_templates/new.html.slim | 3 +
app/views/file_templates/show.html.slim | 7 ++
config/locales/de.yml | 4 +
config/locales/en.yml | 4 +
config/routes.rb | 1 +
.../20160609185708_create_file_templates.rb | 10 +++
db/schema.rb | 10 ++-
16 files changed, 183 insertions(+), 1 deletion(-)
create mode 100644 app/assets/javascripts/file_templates.js.coffee
create mode 100644 app/assets/stylesheets/file_templates.css.scss
create mode 100644 app/controllers/file_templates_controller.rb
create mode 100644 app/models/file_template.rb
create mode 100644 app/policies/file_template_policy.rb
create mode 100644 app/views/file_templates/_form.html.slim
create mode 100644 app/views/file_templates/edit.html.slim
create mode 100644 app/views/file_templates/index.html.slim
create mode 100644 app/views/file_templates/new.html.slim
create mode 100644 app/views/file_templates/show.html.slim
create mode 100644 db/migrate/20160609185708_create_file_templates.rb
diff --git a/app/assets/javascripts/file_templates.js.coffee b/app/assets/javascripts/file_templates.js.coffee
new file mode 100644
index 00000000..24f83d18
--- /dev/null
+++ b/app/assets/javascripts/file_templates.js.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://coffeescript.org/
diff --git a/app/assets/stylesheets/file_templates.css.scss b/app/assets/stylesheets/file_templates.css.scss
new file mode 100644
index 00000000..bf8e27e8
--- /dev/null
+++ b/app/assets/stylesheets/file_templates.css.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the FileTemplates controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/controllers/file_templates_controller.rb b/app/controllers/file_templates_controller.rb
new file mode 100644
index 00000000..45636d61
--- /dev/null
+++ b/app/controllers/file_templates_controller.rb
@@ -0,0 +1,86 @@
+class FileTemplatesController < ApplicationController
+ before_action :set_file_template, only: [:show, :edit, :update, :destroy]
+
+ def authorize!
+ authorize(@file_template || @file_templates)
+ end
+ private :authorize!
+
+ # GET /file_templates
+ # GET /file_templates.json
+ def index
+ @file_templates = FileTemplate.all.order(:file_type_id).paginate(page: params[:page])
+ authorize!
+ end
+
+ # GET /file_templates/1
+ # GET /file_templates/1.json
+ def show
+ authorize!
+ end
+
+ # GET /file_templates/new
+ def new
+ @file_template = FileTemplate.new
+ authorize!
+ end
+
+ # GET /file_templates/1/edit
+ def edit
+ authorize!
+ end
+
+ # POST /file_templates
+ # POST /file_templates.json
+ def create
+ @file_template = FileTemplate.new(file_template_params)
+ authorize!
+
+ respond_to do |format|
+ if @file_template.save
+ format.html { redirect_to @file_template, notice: 'File template was successfully created.' }
+ format.json { render :show, status: :created, location: @file_template }
+ else
+ format.html { render :new }
+ format.json { render json: @file_template.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # PATCH/PUT /file_templates/1
+ # PATCH/PUT /file_templates/1.json
+ def update
+ authorize!
+ respond_to do |format|
+ if @file_template.update(file_template_params)
+ format.html { redirect_to @file_template, notice: 'File template was successfully updated.' }
+ format.json { render :show, status: :ok, location: @file_template }
+ else
+ format.html { render :edit }
+ format.json { render json: @file_template.errors, status: :unprocessable_entity }
+ end
+ end
+ end
+
+ # DELETE /file_templates/1
+ # DELETE /file_templates/1.json
+ def destroy
+ authorize!
+ @file_template.destroy
+ respond_to do |format|
+ format.html { redirect_to file_templates_url, notice: 'File template was successfully destroyed.' }
+ format.json { head :no_content }
+ end
+ end
+
+ private
+ # Use callbacks to share common setup or constraints between actions.
+ def set_file_template
+ @file_template = FileTemplate.find(params[:id])
+ end
+
+ # Never trust parameters from the scary internet, only allow the white list through.
+ def file_template_params
+ params[:file_template].permit(:name, :file_type_id, :content)
+ end
+end
diff --git a/app/models/file_template.rb b/app/models/file_template.rb
new file mode 100644
index 00000000..ef068e13
--- /dev/null
+++ b/app/models/file_template.rb
@@ -0,0 +1,10 @@
+class FileTemplate < ActiveRecord::Base
+
+ belongs_to :file_type
+
+
+ def to_s
+ name
+ end
+
+end
diff --git a/app/models/file_type.rb b/app/models/file_type.rb
index 53bf18dc..d3b519d5 100644
--- a/app/models/file_type.rb
+++ b/app/models/file_type.rb
@@ -12,6 +12,7 @@ class FileType < ActiveRecord::Base
has_many :execution_environments
has_many :files
+ has_many :file_templates
validates :binary, boolean_presence: true
validates :editor_mode, presence: true, unless: :binary?
diff --git a/app/policies/file_template_policy.rb b/app/policies/file_template_policy.rb
new file mode 100644
index 00000000..b2f780a8
--- /dev/null
+++ b/app/policies/file_template_policy.rb
@@ -0,0 +1,7 @@
+class FileTemplatePolicy < AdminOnlyPolicy
+
+ def show?
+ everyone
+ end
+
+end
diff --git a/app/views/file_templates/_form.html.slim b/app/views/file_templates/_form.html.slim
new file mode 100644
index 00000000..1a5c34bc
--- /dev/null
+++ b/app/views/file_templates/_form.html.slim
@@ -0,0 +1,12 @@
+= form_for(@file_template) do |f|
+ = render('shared/form_errors', object: @file_template)
+ .form-group
+ = f.label(:name)
+ = f.text_field(:name, class: 'form-control', required: true)
+ .form-group
+ = f.label(:file_type_id)
+ = f.collection_select(:file_type_id, FileType.all.order(:name), :id, :name, {}, class: 'form-control')
+ .form-group
+ = f.label(:content)
+ = f.text_area(:content, class: 'form-control')
+ .actions = render('shared/submit_button', f: f, object: @file_template)
diff --git a/app/views/file_templates/edit.html.slim b/app/views/file_templates/edit.html.slim
new file mode 100644
index 00000000..c198271f
--- /dev/null
+++ b/app/views/file_templates/edit.html.slim
@@ -0,0 +1,3 @@
+h1 = @file_template
+
+= render('form')
diff --git a/app/views/file_templates/index.html.slim b/app/views/file_templates/index.html.slim
new file mode 100644
index 00000000..3022ea53
--- /dev/null
+++ b/app/views/file_templates/index.html.slim
@@ -0,0 +1,20 @@
+h1 = FileTemplate.model_name.human(count: 2)
+
+.table-responsive
+ table.table
+ thead
+ tr
+ th = t('activerecord.attributes.file_template.name')
+ th = t('activerecord.attributes.file_template.file_type')
+ th colspan=3 = t('shared.actions')
+ tbody
+ - @file_templates.each do |file_template|
+ tr
+ td = file_template.name
+ td = link_to(file_template.file_type, file_type_path(file_template.file_type))
+ td = link_to(t('shared.show'), file_template)
+ td = link_to(t('shared.edit'), edit_file_template_path(file_template))
+ td = link_to(t('shared.destroy'), file_template, data: {confirm: t('shared.confirm_destroy')}, method: :delete)
+
+= render('shared/pagination', collection: @file_templates)
+p = render('shared/new_button', model: FileTemplate)
diff --git a/app/views/file_templates/new.html.slim b/app/views/file_templates/new.html.slim
new file mode 100644
index 00000000..bf434860
--- /dev/null
+++ b/app/views/file_templates/new.html.slim
@@ -0,0 +1,3 @@
+h1 = t('shared.new_model', model: FileTemplate.model_name.human)
+
+= render('form')
diff --git a/app/views/file_templates/show.html.slim b/app/views/file_templates/show.html.slim
new file mode 100644
index 00000000..19f0d28f
--- /dev/null
+++ b/app/views/file_templates/show.html.slim
@@ -0,0 +1,7 @@
+h1
+ = @file_template
+ = render('shared/edit_button', object: @file_template)
+
+= row(label: 'file_template.name', value: @file_template.name)
+= row(label: 'file_template.file_type', value: link_to(@file_template.file_type, file_type_path(@file_template.file_type)))
+= row(label: 'file_template.content', value: @file_template.content)
diff --git a/config/locales/de.yml b/config/locales/de.yml
index e7d78943..4a98e0a0 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -93,6 +93,10 @@ de:
team:
internal_user_ids: Mitglieder
name: Name
+ file_template:
+ name: "Name"
+ file_type: "Dateityp"
+ content: "Code"
models:
code_harbor_link:
one: CodeHarbor-Link
diff --git a/config/locales/en.yml b/config/locales/en.yml
index f2470fc8..de0f3aa4 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -93,6 +93,10 @@ en:
team:
internal_user_ids: Members
name: Name
+ file_template:
+ name: "Name"
+ file_type: "File Type"
+ content: "Content"
models:
code_harbor_link:
one: CodeHarbor Link
diff --git a/config/routes.rb b/config/routes.rb
index 72ccb489..7965f0a3 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,6 +1,7 @@
FILENAME_REGEXP = /[\w\.]+/ unless Kernel.const_defined?(:FILENAME_REGEXP)
Rails.application.routes.draw do
+ resources :file_templates
resources :code_harbor_links
resources :request_for_comments
get '/my_request_for_comments', as: 'my_request_for_comments', to: 'request_for_comments#get_my_comment_requests'
diff --git a/db/migrate/20160609185708_create_file_templates.rb b/db/migrate/20160609185708_create_file_templates.rb
new file mode 100644
index 00000000..43cde0d0
--- /dev/null
+++ b/db/migrate/20160609185708_create_file_templates.rb
@@ -0,0 +1,10 @@
+class CreateFileTemplates < ActiveRecord::Migration
+ def change
+ create_table :file_templates do |t|
+ t.string :name
+ t.text :content
+ t.belongs_to :file_type
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 104a1469..4f7fc833 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20160512131539) do
+ActiveRecord::Schema.define(version: 20160609185708) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -101,6 +101,14 @@ ActiveRecord::Schema.define(version: 20160512131539) do
t.datetime "updated_at"
end
+ create_table "file_templates", force: true do |t|
+ t.string "name"
+ t.text "content"
+ t.integer "file_type_id"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
create_table "file_types", force: true do |t|
t.string "editor_mode"
t.string "file_extension"
From 1e4ab7cabe2ea052d4c1251a7c6c7549559b4057 Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Fri, 10 Jun 2016 11:54:11 +0200
Subject: [PATCH 26/81] py_unit_adapter now also counts errors, not just
failures
---
lib/py_unit_adapter.rb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/py_unit_adapter.rb b/lib/py_unit_adapter.rb
index f7f98dae..23b86ae9 100644
--- a/lib/py_unit_adapter.rb
+++ b/lib/py_unit_adapter.rb
@@ -1,6 +1,6 @@
class PyUnitAdapter < TestingFrameworkAdapter
COUNT_REGEXP = /Ran (\d+) test/
- FAILURES_REGEXP = /FAILED \(failures=(\d+)\)/
+ FAILURES_REGEXP = /FAILED \((failures)|(errors)=(\d+)\)/
ASSERTION_ERROR_REGEXP = /AssertionError:\s(.*)/
def self.framework_name
@@ -10,7 +10,7 @@ class PyUnitAdapter < TestingFrameworkAdapter
def parse_output(output)
count = COUNT_REGEXP.match(output[:stderr]).captures.first.to_i
matches = FAILURES_REGEXP.match(output[:stderr])
- failed = matches ? matches.captures.try(:first).to_i : 0
+ failed = matches ? matches.captures.try(:third).to_i : 0
error_matches = ASSERTION_ERROR_REGEXP.match(output[:stderr]).try(:captures) || []
{count: count, failed: failed, error_messages: error_matches}
end
From 4f8feb38e10c7e3591a6f7c60436c45dbd67e29d Mon Sep 17 00:00:00 2001
From: Maximilian Grundke
Date: Fri, 10 Jun 2016 13:41:38 +0200
Subject: [PATCH 27/81] Use file template to generate new file content
---
app/controllers/code_ocean/files_controller.rb | 3 +++
app/controllers/concerns/file_parameters.rb | 2 +-
app/views/code_ocean/files/_form.html.slim | 3 +++
config/locales/de.yml | 1 +
config/locales/en.yml | 1 +
db/migrate/20160610111602_add_file_template_to_file.rb | 5 +++++
db/schema.rb | 3 ++-
7 files changed, 16 insertions(+), 2 deletions(-)
create mode 100644 db/migrate/20160610111602_add_file_template_to_file.rb
diff --git a/app/controllers/code_ocean/files_controller.rb b/app/controllers/code_ocean/files_controller.rb
index 74c1932f..e38607c2 100644
--- a/app/controllers/code_ocean/files_controller.rb
+++ b/app/controllers/code_ocean/files_controller.rb
@@ -10,6 +10,9 @@ module CodeOcean
def create
@file = CodeOcean::File.new(file_params)
+ if @file.file_template_id
+ @file.content = FileTemplate.find(@file.file_template_id).content
+ end
authorize!
create_and_respond(object: @file, path: proc { implement_exercise_path(@file.context.exercise, tab: 2) })
end
diff --git a/app/controllers/concerns/file_parameters.rb b/app/controllers/concerns/file_parameters.rb
index e61e719e..295b66c3 100644
--- a/app/controllers/concerns/file_parameters.rb
+++ b/app/controllers/concerns/file_parameters.rb
@@ -1,6 +1,6 @@
module FileParameters
def file_attributes
- %w(content context_id feedback_message file_id file_type_id hidden id name native_file path read_only role weight)
+ %w(content context_id feedback_message file_id file_type_id hidden id name native_file path read_only role weight file_template_id)
end
private :file_attributes
end
diff --git a/app/views/code_ocean/files/_form.html.slim b/app/views/code_ocean/files/_form.html.slim
index 07dd3355..ee74f4b8 100644
--- a/app/views/code_ocean/files/_form.html.slim
+++ b/app/views/code_ocean/files/_form.html.slim
@@ -8,5 +8,8 @@
.form-group
= f.label(:file_type_id, t('activerecord.attributes.file.file_type_id'))
= f.collection_select(:file_type_id, FileType.where(binary: false).order(:name), :id, :name, {selected: @exercise.execution_environment.file_type.try(:id)}, class: 'form-control')
+ .form-group
+ = f.label(:file_template_id, t('activerecord.attributes.file.file_template_id'))
+ = f.collection_select(:file_template_id, FileTemplate.all.order(:name), :id, :name, {}, class: 'form-control')
= f.hidden_field(:context_id)
.actions = render('shared/submit_button', f: f, object: CodeOcean::File.new)
diff --git a/config/locales/de.yml b/config/locales/de.yml
index 4a98e0a0..9a48ee4f 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -54,6 +54,7 @@ de:
read_only: Schreibgeschützt
role: Rolle
weight: Punktzahl
+ file_template_id: "Dateivorlage"
file_type:
binary: Binär
editor_mode: Editor-Modus
diff --git a/config/locales/en.yml b/config/locales/en.yml
index de0f3aa4..49fc8bbb 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -54,6 +54,7 @@ en:
read_only: Read-only
role: Role
weight: Score
+ file_template_id: "File Template"
file_type:
binary: Binary
editor_mode: Editor Mode
diff --git a/db/migrate/20160610111602_add_file_template_to_file.rb b/db/migrate/20160610111602_add_file_template_to_file.rb
new file mode 100644
index 00000000..a595e90b
--- /dev/null
+++ b/db/migrate/20160610111602_add_file_template_to_file.rb
@@ -0,0 +1,5 @@
+class AddFileTemplateToFile < ActiveRecord::Migration
+ def change
+ add_reference :files, :file_template
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 4f7fc833..bed23c98 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20160609185708) do
+ActiveRecord::Schema.define(version: 20160610111602) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -140,6 +140,7 @@ ActiveRecord::Schema.define(version: 20160609185708) do
t.string "feedback_message"
t.float "weight"
t.string "path"
+ t.integer "file_template_id"
end
add_index "files", ["context_id", "context_type"], name: "index_files_on_context_id_and_context_type", using: :btree
From c10b07690ad29138dd7be79bc2fdf21836b90b48 Mon Sep 17 00:00:00 2001
From: Maximilian Grundke
Date: Fri, 10 Jun 2016 13:46:13 +0200
Subject: [PATCH 28/81] Make file template optional
---
app/views/code_ocean/files/_form.html.slim | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/views/code_ocean/files/_form.html.slim b/app/views/code_ocean/files/_form.html.slim
index ee74f4b8..4b44647d 100644
--- a/app/views/code_ocean/files/_form.html.slim
+++ b/app/views/code_ocean/files/_form.html.slim
@@ -10,6 +10,6 @@
= f.collection_select(:file_type_id, FileType.where(binary: false).order(:name), :id, :name, {selected: @exercise.execution_environment.file_type.try(:id)}, class: 'form-control')
.form-group
= f.label(:file_template_id, t('activerecord.attributes.file.file_template_id'))
- = f.collection_select(:file_template_id, FileTemplate.all.order(:name), :id, :name, {}, class: 'form-control')
+ = f.collection_select(:file_template_id, FileTemplate.all.order(:name), :id, :name, {:include_blank => true}, class: 'form-control')
= f.hidden_field(:context_id)
.actions = render('shared/submit_button', f: f, object: CodeOcean::File.new)
From 4d2676fea75a724faed1ef7a2beaf0d04d22c4c2 Mon Sep 17 00:00:00 2001
From: Maximilian Grundke
Date: Fri, 10 Jun 2016 17:48:04 +0200
Subject: [PATCH 29/81] Only show file templates which are available for the
selected file type
---
app/assets/javascripts/exercises.js | 20 ++++++++++++++++++++
app/controllers/file_templates_controller.rb | 8 ++++++++
app/policies/file_template_policy.rb | 4 ++++
app/views/code_ocean/files/_form.html.slim | 1 +
config/locales/de.yml | 2 ++
config/locales/en.yml | 2 ++
config/routes.rb | 6 +++++-
7 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/app/assets/javascripts/exercises.js b/app/assets/javascripts/exercises.js
index 1f861ef6..0e3805db 100644
--- a/app/assets/javascripts/exercises.js
+++ b/app/assets/javascripts/exercises.js
@@ -148,6 +148,22 @@ $(function() {
});
};
+ var updateFileTemplates = function(fileType) {
+ var jqxhr = $.ajax({
+ url: '/file_templates/by_file_type/' + fileType + '.json',
+ dataType: 'json'
+ });
+ jqxhr.done(function(response) {
+ var noTemplateLabel = $('#noTemplateLabel').data('text');
+ var options = "" + noTemplateLabel + " ";
+ for (var i = 0; i < response.length; i++) {
+ options += "" + response[i].name + " "
+ }
+ $("#code_ocean_file_file_template_id").find('option').remove().end().append($(options));
+ });
+ jqxhr.fail(ajaxError);
+ }
+
if ($.isController('exercises')) {
if ($('table').isPresent()) {
enableBatchUpdate();
@@ -162,6 +178,10 @@ $(function() {
inferFileAttributes();
observeFileRoleChanges();
overrideTextareaTabBehavior();
+ } else if ($('#files.jstree').isPresent()) {
+ var fileTypeSelect = $('#code_ocean_file_file_type_id');
+ fileTypeSelect.on("change", function() {updateFileTemplates(fileTypeSelect.val())});
+ updateFileTemplates(fileTypeSelect.val());
}
toggleCodeHeight();
if (window.hljs) {
diff --git a/app/controllers/file_templates_controller.rb b/app/controllers/file_templates_controller.rb
index 45636d61..a6039500 100644
--- a/app/controllers/file_templates_controller.rb
+++ b/app/controllers/file_templates_controller.rb
@@ -6,6 +6,14 @@ class FileTemplatesController < ApplicationController
end
private :authorize!
+ def by_file_type
+ @file_templates = FileTemplate.where(:file_type_id => params[:file_type_id])
+ authorize!
+ respond_to do |format|
+ format.json { render :show, status: :ok, json: @file_templates.to_json }
+ end
+ end
+
# GET /file_templates
# GET /file_templates.json
def index
diff --git a/app/policies/file_template_policy.rb b/app/policies/file_template_policy.rb
index b2f780a8..92ced442 100644
--- a/app/policies/file_template_policy.rb
+++ b/app/policies/file_template_policy.rb
@@ -4,4 +4,8 @@ class FileTemplatePolicy < AdminOnlyPolicy
everyone
end
+ def by_file_type?
+ everyone
+ end
+
end
diff --git a/app/views/code_ocean/files/_form.html.slim b/app/views/code_ocean/files/_form.html.slim
index 4b44647d..46c5b2c2 100644
--- a/app/views/code_ocean/files/_form.html.slim
+++ b/app/views/code_ocean/files/_form.html.slim
@@ -12,4 +12,5 @@
= f.label(:file_template_id, t('activerecord.attributes.file.file_template_id'))
= f.collection_select(:file_template_id, FileTemplate.all.order(:name), :id, :name, {:include_blank => true}, class: 'form-control')
= f.hidden_field(:context_id)
+ .hidden#noTemplateLabel data-text=t('file_template.no_template_label')
.actions = render('shared/submit_button', f: f, object: CodeOcean::File.new)
diff --git a/config/locales/de.yml b/config/locales/de.yml
index 9a48ee4f..c0aa4b13 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -432,3 +432,5 @@ de:
next_label: 'Nächste Seite →'
page_gap: '…'
previous_label: '← Vorherige Seite'
+ file_template:
+ no_template_label: "Leere Datei"
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 49fc8bbb..f03e42fb 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -432,3 +432,5 @@ en:
next_label: 'Next Page →'
page_gap: '…'
previous_label: '← Previous Page'
+ file_template:
+ no_template_label: "Empty File"
diff --git a/config/routes.rb b/config/routes.rb
index 7965f0a3..afd8c8ce 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,7 +1,11 @@
FILENAME_REGEXP = /[\w\.]+/ unless Kernel.const_defined?(:FILENAME_REGEXP)
Rails.application.routes.draw do
- resources :file_templates
+ resources :file_templates do
+ collection do
+ get 'by_file_type/:file_type_id', as: :by_file_type, to: :by_file_type
+ end
+ end
resources :code_harbor_links
resources :request_for_comments
get '/my_request_for_comments', as: 'my_request_for_comments', to: 'request_for_comments#get_my_comment_requests'
From 8d030e42e9621391c4c9aa4a7de32eb731cdba27 Mon Sep 17 00:00:00 2001
From: Maximilian Grundke
Date: Fri, 10 Jun 2016 18:08:57 +0200
Subject: [PATCH 30/81] Allow templates to include the file name as a macro
---
app/controllers/code_ocean/files_controller.rb | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/app/controllers/code_ocean/files_controller.rb b/app/controllers/code_ocean/files_controller.rb
index e38607c2..55d8b369 100644
--- a/app/controllers/code_ocean/files_controller.rb
+++ b/app/controllers/code_ocean/files_controller.rb
@@ -11,7 +11,9 @@ module CodeOcean
def create
@file = CodeOcean::File.new(file_params)
if @file.file_template_id
- @file.content = FileTemplate.find(@file.file_template_id).content
+ content = FileTemplate.find(@file.file_template_id).content
+ content.sub! '{{file_name}}', @file.name
+ @file.content = content
end
authorize!
create_and_respond(object: @file, path: proc { implement_exercise_path(@file.context.exercise, tab: 2) })
From 7ef401f75aa97c9dd4fc86ec7deb87151891d187 Mon Sep 17 00:00:00 2001
From: Maximilian Grundke
Date: Fri, 10 Jun 2016 18:15:37 +0200
Subject: [PATCH 31/81] Add navigation item for file templates
---
app/views/application/_navigation.html.slim | 2 +-
config/locales/de.yml | 3 +++
config/locales/en.yml | 3 +++
3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/app/views/application/_navigation.html.slim b/app/views/application/_navigation.html.slim
index 4ab39e30..0f859844 100644
--- a/app/views/application/_navigation.html.slim
+++ b/app/views/application/_navigation.html.slim
@@ -8,7 +8,7 @@
- if current_user.admin?
li = link_to(t('breadcrumbs.dashboard.show'), admin_dashboard_path)
li.divider
- - models = [ExecutionEnvironment, Exercise, Consumer, CodeHarborLink, ExternalUser, FileType, InternalUser, Submission, Team].sort_by { |model| model.model_name.human(count: 2) }
+ - models = [ExecutionEnvironment, Exercise, Consumer, CodeHarborLink, ExternalUser, FileType, FileTemplate, InternalUser, Submission, Team].sort_by { |model| model.model_name.human(count: 2) }
- models.each do |model|
- if policy(model).index?
li = link_to(model.model_name.human(count: 2), send(:"#{model.model_name.collection}_path"))
diff --git a/config/locales/de.yml b/config/locales/de.yml
index c0aa4b13..c0013777 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -120,6 +120,9 @@ de:
file:
one: Datei
other: Dateien
+ file_template:
+ one: Dateivorlage
+ other: Dateivorlagen
file_type:
one: Dateityp
other: Dateitypen
diff --git a/config/locales/en.yml b/config/locales/en.yml
index f03e42fb..1d597bf8 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -120,6 +120,9 @@ en:
file:
one: File
other: Files
+ file_template:
+ one: File Template
+ other: File Templates
file_type:
one: File Type
other: File Types
From 74b33492cb58a25c2efca4fff1f4a9c52c14dd4c Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Tue, 14 Jun 2016 10:42:15 +0200
Subject: [PATCH 32/81] fixed python failure regex.
---
lib/py_unit_adapter.rb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/py_unit_adapter.rb b/lib/py_unit_adapter.rb
index 23b86ae9..11b8cb09 100644
--- a/lib/py_unit_adapter.rb
+++ b/lib/py_unit_adapter.rb
@@ -1,6 +1,6 @@
class PyUnitAdapter < TestingFrameworkAdapter
COUNT_REGEXP = /Ran (\d+) test/
- FAILURES_REGEXP = /FAILED \((failures)|(errors)=(\d+)\)/
+ FAILURES_REGEXP = /FAILED \((failures|errors)=(\d+)\)/
ASSERTION_ERROR_REGEXP = /AssertionError:\s(.*)/
def self.framework_name
@@ -10,7 +10,7 @@ class PyUnitAdapter < TestingFrameworkAdapter
def parse_output(output)
count = COUNT_REGEXP.match(output[:stderr]).captures.first.to_i
matches = FAILURES_REGEXP.match(output[:stderr])
- failed = matches ? matches.captures.try(:third).to_i : 0
+ failed = matches ? matches.captures.try(:second).to_i : 0
error_matches = ASSERTION_ERROR_REGEXP.match(output[:stderr]).try(:captures) || []
{count: count, failed: failed, error_messages: error_matches}
end
From f2e2c232e48b42e5c3e7c70299c1e41466ddfc35 Mon Sep 17 00:00:00 2001
From: yqbk
Date: Tue, 14 Jun 2016 17:01:50 +0200
Subject: [PATCH 33/81] round result to fixed 2 digits
---
app/assets/javascripts/editor.js.erb | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb
index 0bb22853..10123521 100644
--- a/app/assets/javascripts/editor.js.erb
+++ b/app/assets/javascripts/editor.js.erb
@@ -707,7 +707,8 @@ $(function() {
var score = $('#score').data('score');
var maxium_score = $('#score').data('maximum-score');
if (score >= 0 && score <= maxium_score && maxium_score >0 ) {
- var percentage_score = score / maxium_score * 100
+ var rounded_number = (score / maxium_score ).toFixed(2);
+ var percentage_score = rounded_number * 100
$('.score').html(percentage_score + '%');
}
else {
From d5b78c29da39c15df6a61e7de1da83cf2b3f1e63 Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Tue, 14 Jun 2016 17:19:52 +0200
Subject: [PATCH 34/81] Fixed rounding issue caused by JavaScript and the
conversion to String.
---
app/assets/javascripts/editor.js.erb | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb
index 10123521..50217b1f 100644
--- a/app/assets/javascripts/editor.js.erb
+++ b/app/assets/javascripts/editor.js.erb
@@ -707,8 +707,7 @@ $(function() {
var score = $('#score').data('score');
var maxium_score = $('#score').data('maximum-score');
if (score >= 0 && score <= maxium_score && maxium_score >0 ) {
- var rounded_number = (score / maxium_score ).toFixed(2);
- var percentage_score = rounded_number * 100
+ var percentage_score = (score / maxium_score * 100 ).toFixed(2);
$('.score').html(percentage_score + '%');
}
else {
From a1ead9658e22f413eadd719a1c251bfbb49c9bce Mon Sep 17 00:00:00 2001
From: tstaubitz
Date: Tue, 14 Jun 2016 17:27:15 +0200
Subject: [PATCH 35/81] Update de.yml
---
config/locales/de.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/config/locales/de.yml b/config/locales/de.yml
index 30f4f7ef..ae7fb930 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -212,7 +212,7 @@ de:
exercise_deadline_passed: 'Die Abgabefrist für diese Aufgabe ist bereits abgelaufen.'
tooltips:
save: Ihr Code wird automatisch gespeichert, wann immer Sie eine Datei herunterladen, ausführen oder testen. Explizites Speichern ist also selten notwendig.
- exercise_deadline_passed: 'Die hier erzielten Punkten können nur bis zum Ablauf der Abgabefrist an die E-Learning-Plattform übertragen werden.'
+ exercise_deadline_passed: 'Die hier erzielten Punkte können nur bis zum Ablauf der Abgabefrist an die E-Learning-Plattform übertragen werden.'
request_for_comments_sent: "Kommentaranfrage gesendet."
editor_file_tree:
file_root: Dateien
From 8ddf1e158e02410874fe4354ae6eb3067f2cdc2e Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Tue, 14 Jun 2016 17:53:54 +0200
Subject: [PATCH 36/81] Fixed background and pen coloring on client side
(javascript).
See: https://github.com/openHPI/codeocean/issues/59
Kudos to waywwaard.
---
app/assets/javascripts/turtle.js | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/app/assets/javascripts/turtle.js b/app/assets/javascripts/turtle.js
index f2fa184b..ddbb27eb 100644
--- a/app/assets/javascripts/turtle.js
+++ b/app/assets/javascripts/turtle.js
@@ -41,8 +41,7 @@ Turtle.prototype.update = function () {
var i, k, canvas, ctx, dx, dy, item, c, length;
canvas = this.canvas[0];
ctx = canvas.getContext('2d');
- ctx.fillStyle = '#fff';
- ctx.fillRect(0, 0, canvas.width, canvas.height);
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
length = this.items.length;
dx = canvas.width / 2;
dy = canvas.height / 2;
@@ -56,8 +55,8 @@ Turtle.prototype.update = function () {
for (k = 2; k < c.length; k += 2) {
ctx.lineTo(c[k] + dx, c[k + 1] + dy);
}
- if (this.fill) {
- ctx.strokeStyle = this.fill;
+ if (item.fill) {
+ ctx.strokeStyle = item.fill;
}
ctx.stroke();
From 894f8abda233fd00dd0efe6bcb2b2cd704592f63 Mon Sep 17 00:00:00 2001
From: yqbk
Date: Wed, 15 Jun 2016 12:03:34 +0200
Subject: [PATCH 37/81] round result to fixed 0 digits in percentage output
---
app/assets/javascripts/editor.js.erb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb
index 50217b1f..f000a23a 100644
--- a/app/assets/javascripts/editor.js.erb
+++ b/app/assets/javascripts/editor.js.erb
@@ -707,7 +707,7 @@ $(function() {
var score = $('#score').data('score');
var maxium_score = $('#score').data('maximum-score');
if (score >= 0 && score <= maxium_score && maxium_score >0 ) {
- var percentage_score = (score / maxium_score * 100 ).toFixed(2);
+ var percentage_score = (score / maxium_score * 100 ).toFixed(0);
$('.score').html(percentage_score + '%');
}
else {
From fbb83e3057ddb4fe01c77badb8d637bc8df4e618 Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Thu, 16 Jun 2016 11:38:16 +0200
Subject: [PATCH 38/81] fix comparison problem caused by javascript comparisons
based on Strings. ("1.00" <= "1.0" --> false)
---
app/assets/javascripts/editor.js.erb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb
index f000a23a..1e64195e 100644
--- a/app/assets/javascripts/editor.js.erb
+++ b/app/assets/javascripts/editor.js.erb
@@ -704,8 +704,8 @@ $(function() {
};
var renderScore = function() {
- var score = $('#score').data('score');
- var maxium_score = $('#score').data('maximum-score');
+ var score = parseFloat($('#score').data('score'));
+ var maxium_score = parseFloat($('#score').data('maximum-score'));
if (score >= 0 && score <= maxium_score && maxium_score >0 ) {
var percentage_score = (score / maxium_score * 100 ).toFixed(0);
$('.score').html(percentage_score + '%');
From 9e644563e3eae71b48b990323c3d9fd545628cf9 Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Thu, 16 Jun 2016 11:39:13 +0200
Subject: [PATCH 39/81] adapt regex for py_unit_adapter once more... hopefully
we got all cases now.
---
lib/py_unit_adapter.rb | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/lib/py_unit_adapter.rb b/lib/py_unit_adapter.rb
index 11b8cb09..1ff5cd98 100644
--- a/lib/py_unit_adapter.rb
+++ b/lib/py_unit_adapter.rb
@@ -1,6 +1,7 @@
class PyUnitAdapter < TestingFrameworkAdapter
COUNT_REGEXP = /Ran (\d+) test/
- FAILURES_REGEXP = /FAILED \((failures|errors)=(\d+)\)/
+ FAILURES_REGEXP = /FAILED \(.*failures=(\d+).*\)/
+ ERRORS_REGEXP = /FAILED \(.*errors=(\d+).*\)/
ASSERTION_ERROR_REGEXP = /AssertionError:\s(.*)/
def self.framework_name
@@ -9,9 +10,11 @@ class PyUnitAdapter < TestingFrameworkAdapter
def parse_output(output)
count = COUNT_REGEXP.match(output[:stderr]).captures.first.to_i
- matches = FAILURES_REGEXP.match(output[:stderr])
- failed = matches ? matches.captures.try(:second).to_i : 0
- error_matches = ASSERTION_ERROR_REGEXP.match(output[:stderr]).try(:captures) || []
- {count: count, failed: failed, error_messages: error_matches}
+ failures_matches = FAILURES_REGEXP.match(output[:stderr])
+ failed = failures_matches ? failures_matches.captures.try(:first).to_i : 0
+ error_matches = ERRORS_REGEXP.match(output[:stderr])
+ errors = error_matches ? error_matches.captures.try(:first).to_i : 0
+ assertion_error_matches = ASSERTION_ERROR_REGEXP.match(output[:stderr]).try(:captures) || []
+ {count: count, failed: failed + errors, error_messages: assertion_error_matches}
end
end
From ec26a095f692e2102e8a87ea85d36e1655582099 Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Fri, 17 Jun 2016 14:48:57 +0200
Subject: [PATCH 40/81] First working version of mails on comments.
---
app/controllers/comments_controller.rb | 14 +++++++++++---
app/mailers/user_mailer.rb | 10 +++++++---
app/views/request_for_comments/show.html.erb | 5 +++--
app/views/user_mailer/got_new_comment.slim | 2 +-
config/locales/de.yml | 7 +++++++
config/locales/en.yml | 10 ++++++++++
6 files changed, 39 insertions(+), 9 deletions(-)
diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb
index fd6840ff..fe7f454c 100644
--- a/app/controllers/comments_controller.rb
+++ b/app/controllers/comments_controller.rb
@@ -46,7 +46,11 @@ class CommentsController < ApplicationController
# POST /comments
# POST /comments.json
def create
- @comment = Comment.new(comment_params)
+ @comment = Comment.new(comment_params_without_request_id)
+
+ if comment_params[:request_id]
+ UserMailer.got_new_comment(@comment, RequestForComment.find(comment_params[:request_id]), current_user)
+ end
respond_to do |format|
if @comment.save
@@ -64,7 +68,7 @@ class CommentsController < ApplicationController
# PATCH/PUT /comments/1.json
def update
respond_to do |format|
- if @comment.update(comment_params)
+ if @comment.update(comment_params_without_request_id)
format.html { head :no_content, notice: 'Comment was successfully updated.' }
format.json { render :show, status: :ok, location: @comment }
else
@@ -101,10 +105,14 @@ class CommentsController < ApplicationController
@comment = Comment.find(params[:id])
end
+ def comment_params_without_request_id
+ comment_params.except :request_id
+ end
+
# Never trust parameters from the scary internet, only allow the white list through.
def comment_params
#params.require(:comment).permit(:user_id, :file_id, :row, :column, :text)
# fuer production mode, damit böse menschen keine falsche user_id uebergeben:
- params.require(:comment).permit(:file_id, :row, :column, :text).merge(user_id: current_user.id, user_type: current_user.class.name)
+ params.require(:comment).permit(:file_id, :row, :column, :text, :request_id).merge(user_id: current_user.id, user_type: current_user.class.name)
end
end
diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb
index 8cb5eed1..e1773d48 100644
--- a/app/mailers/user_mailer.rb
+++ b/app/mailers/user_mailer.rb
@@ -12,8 +12,12 @@ class UserMailer < ActionMailer::Base
mail(subject: t('mailers.user_mailer.reset_password.subject'), to: user.email)
end
- def got_new_comment(comment, user, commenting_user)
- @commenting_user = commenting_user
- mail(subject: t('mailers.user_mailer.got_new_comment.subject'), to: user.email)
+ def got_new_comment(comment, request_for_comment, commenting_user)
+ # todo: check whether we can take the last known locale of the receiver?
+ @receiver_displayname = request_for_comment.user.displayname
+ @commenting_user_displayname = commenting_user.displayname
+ @comment_text = comment.text
+ @rfc_link = request_for_comment_url(request_for_comment)
+ mail(subject: t('mailers.user_mailer.got_new_comment.subject', commenting_user_displayname: @commenting_user_displayname), to: request_for_comment.user.email).deliver
end
end
diff --git a/app/views/request_for_comments/show.html.erb b/app/views/request_for_comments/show.html.erb
index e4dc7f06..1d6bb54c 100644
--- a/app/views/request_for_comments/show.html.erb
+++ b/app/views/request_for_comments/show.html.erb
@@ -1,5 +1,5 @@
-
<%= Exercise.find(@request_for_comment.exercise_id) %>
+
<%= Exercise.find(@request_for_comment.exercise_id) %>
<%
user = @request_for_comment.user
@@ -101,7 +101,8 @@ do not put a carriage return in the line below. it will be present in the presen
file_id: file_id,
row: row,
column: 0,
- text: commenttext
+ text: commenttext,
+ request_id: $('h4').data('rfc-id')
}
},
dataType: 'json',
diff --git a/app/views/user_mailer/got_new_comment.slim b/app/views/user_mailer/got_new_comment.slim
index 3b8afa5b..656e245d 100644
--- a/app/views/user_mailer/got_new_comment.slim
+++ b/app/views/user_mailer/got_new_comment.slim
@@ -1 +1 @@
-== t('mailers.user_mailer.activation_needed.body', link: link_to(@activation_url, @activation_url))
+== t('mailers.user_mailer.got_new_comment.body', receiver_displayname: @receiver_displayname, link: link_to(@rfc_link, @rfc_link), commenting_user_displayname: @commenting_user_displayname, comment_text: @comment_text)
diff --git a/config/locales/de.yml b/config/locales/de.yml
index ae7fb930..a3b580b5 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -325,6 +325,13 @@ de:
activation_needed:
body: 'Bitte besuchen Sie %{link} und wählen Sie ein Passwort, um Ihre Registrierung abzuschließen.'
subject: Bitte schließen Sie Ihre Registrierung ab.
+ got_new_comment:
+ body: |
+ Hallo %{receiver_displayname},
+
+ es gibt einen neuen Kommentar von %{commenting_user_displayname} zu Ihrer Kommentaranfrage auf CodeOcean.
+ Sie finden ihn hier: %{link}
+ subject: Sie haben einen neuen Kommentar von %{commenting_user_displayname} auf CodeOcean erhalten.
reset_password:
body: 'Bitte besuchen Sie %{link}, sofern Sie Ihr Passwort zurücksetzen wollen.'
subject: Anweisungen zum Zurücksetzen Ihres Passworts
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 6cc9dcaf..1162971d 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -325,6 +325,16 @@ en:
activation_needed:
body: 'Please visit %{link} and set up a password in order to complete your registration.'
subject: Please complete your registration.
+ got_new_comment:
+ body: |
+ Dear %{receiver_displayname},
+
+ you received a new comment from %{commenting_user_displayname} to your request for comments on CodeOcean.
+ You can find it here: %{link}
+
+ Best regards,
+ your Teaching Team
+ subject: 'You received a new comment on CodeOcean from %{commenting_user_displayname}.'
reset_password:
body: 'Please visit %{link} if you want to reset your password.'
subject: Password reset instructions
From 003e89b23043645cf0ec01e4473722a8f18f8805 Mon Sep 17 00:00:00 2001
From: John Geiger
Date: Fri, 17 Jun 2016 15:03:07 +0200
Subject: [PATCH 41/81] x axis stuff
---
app/assets/javascripts/exercise_graphs.js | 33 +++++++----------------
1 file changed, 10 insertions(+), 23 deletions(-)
diff --git a/app/assets/javascripts/exercise_graphs.js b/app/assets/javascripts/exercise_graphs.js
index f5640788..f98509b3 100644
--- a/app/assets/javascripts/exercise_graphs.js
+++ b/app/assets/javascripts/exercise_graphs.js
@@ -141,20 +141,13 @@ $(function() {
if(largestSubmittedTimeStamp.cause == "assess"){
largestArrayForRange = submissionsScoreAndTimeAssess;
- indexForTime = 1;
- } else if(largestSubmittedTimeStamp.cause == "submit"){
- largestArrayForRange = submissionsScoreAndTimeSubmits;
- indexForTime = 1;
- } else if(largestSubmittedTimeStamp.cause == "run"){
- largestArrayForRange = submissionsScoreAndTimeRuns;
- indexForTime = 0;
x.domain([0,largestArrayForRange[largestArrayForRange.length - 1][1]]).clamp(true);
} else if(largestSubmittedTimeStamp.cause == "submit"){
largestArrayForRange = submissionsScoreAndTimeSubmits;
x.domain([0,largestArrayForRange[largestArrayForRange.length - 1][1]]).clamp(true);
} else if(largestSubmittedTimeStamp.cause == "run"){
largestArrayForRange = submissionsScoreAndTimeRuns;
- x.domain([0,largestArrayForRange[largestArrayForRange.length - 1][1]]).clamp(true);
+ x.domain([0,largestArrayForRange[largestArrayForRange.length - 1]]).clamp(true);
} else if(largestSubmittedTimeStamp.cause == "autosave"){
largestArrayForRange = submissionsAutosaves;
x.domain([0,largestArrayForRange[largestArrayForRange.length - 1]]).clamp(true);
@@ -162,12 +155,6 @@ $(function() {
largestArrayForRange = submissionsSaves;
x.domain([0,largestArrayForRange[largestArrayForRange.length - 1]]).clamp(true);
}
-
- // x.domain(d3.extent(largestArrayForRange, function (d) {
- // // console.log(d[1]);
- // return (d[indexForTime]);
- // }));
-
// take maximum value between assesses and submits
var yDomain = submissionsScoreAndTimeAssess.concat(submissionsScoreAndTimeSubmits);
y.domain(d3.extent(yDomain, function (d) {
@@ -212,15 +199,15 @@ $(function() {
.style('font-size', 20)
.style('text-decoration', 'underline');
- //
- // svg.append("path")
- // //.datum()
- // .attr("class", "line")
- // .attr('id', 'myPath')// new
- // .attr("stroke", "black")
- // .attr("stroke-width", 5)
- // .attr("fill", "none")// end new
- // .attr("d", line(submissionsScoreAndTimeAssess));//---
+
+ svg.append("path")
+ //.datum()
+ .attr("class", "line")
+ .attr('id', 'myPath')// new
+ .attr("stroke", "black")
+ .attr("stroke-width", 5)
+ .attr("fill", "none")// end new
+ .attr("d", line(submissionsScoreAndTimeAssess));//---
svg.append("path")
.datum(submissionsScoreAndTimeAssess)
From 5840b626922ba4e990a2f6ff9b11f501594966ad Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Fri, 17 Jun 2016 15:04:17 +0200
Subject: [PATCH 42/81] 2nd part of the fix.
---
app/assets/javascripts/exercise_graphs.js | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/app/assets/javascripts/exercise_graphs.js b/app/assets/javascripts/exercise_graphs.js
index f98509b3..5f521b39 100644
--- a/app/assets/javascripts/exercise_graphs.js
+++ b/app/assets/javascripts/exercise_graphs.js
@@ -226,20 +226,17 @@ $(function() {
.attr("cx", function(d) { return x(d[1]); })
.attr("cy", function(d) { return y(d[0]); });
-
- svg.append("path")
- .datum(submissionsScoreAndTimeSubmits)
- .attr("class", "line2")
- .attr('id', 'myPath')// new
- .attr("stroke", "blue")
- .attr("stroke-width", 5)
- .attr("fill", "none")// end new
- .attr("d", line);//---
+ if (submissionsScoreAndTimeSubmits.length > 0){
+ // get rid of the 0 element at the beginning
+ submissionsScoreAndTimeSubmits.shift();
+ }
svg.selectAll("dot") // Add dots to submits
.data(submissionsScoreAndTimeSubmits)
.enter().append("circle")
- .attr("r", 3.5)
+ .attr("r", 6)
+ .attr("stroke", "black")
+ .attr("fill", "blue")
.attr("cx", function(d) { return x(d[1]); })
.attr("cy", function(d) { return y(d[0]); });
From 96de763b8314c0fb6a194fc985cb6191c651dbe0 Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Fri, 17 Jun 2016 16:42:07 +0200
Subject: [PATCH 43/81] Handle scoring presentation to client via websockets
---
app/assets/javascripts/editor.js.erb | 19 ++++++++++---------
app/controllers/submissions_controller.rb | 6 +++++-
2 files changed, 15 insertions(+), 10 deletions(-)
diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb
index 1e64195e..f9555e92 100644
--- a/app/assets/javascripts/editor.js.erb
+++ b/app/assets/javascripts/editor.js.erb
@@ -184,8 +184,8 @@ $(function() {
(streamed ? evaluateCodeWithStreamedResponse : evaluateCodeWithoutStreamedResponse)(url, callback);
};
- var evaluateCodeWithStreamedResponse = function(url, callback) {
- initWebsocketConnection(url);
+ var evaluateCodeWithStreamedResponse = function(url, onmessageFunction) {
+ initWebsocketConnection(url, onmessageFunction);
// TODO only init turtle when required
initTurtle();
@@ -306,9 +306,10 @@ $(function() {
}
};
- var handleScoringResponse = function(response) {
- printScoringResults(response);
- var score = _.reduce(response, function(sum, result) {
+ var handleScoringResponse = function(websocket_event) {
+ results = JSON.parse(websocket_event.data);
+ printScoringResults(results);
+ var score = _.reduce(results, function(sum, result) {
return sum + result.score * result.weight;
}, 0).toFixed(2);
$('#score').data('score', score);
@@ -743,7 +744,7 @@ $(function() {
showSpinner($('#run'));
toggleButtonStates();
var url = response.run_url.replace(FILENAME_URL_PLACEHOLDER, active_file.filename);
- evaluateCode(url, true, printChunk);
+ evaluateCode(url, true, function(evt) { parseCanvasMessage(evt.data, true); });
});
}
};
@@ -778,7 +779,7 @@ $(function() {
createSubmission(this, null, function(response) {
showSpinner($('#assess'));
var url = response.score_url;
- evaluateCode(url, false, handleScoringResponse);
+ evaluateCode(url, true, handleScoringResponse);
});
};
@@ -974,14 +975,14 @@ $(function() {
$('#test').toggle(isActiveFileTestable());
};
- var initWebsocketConnection = function(url) {
+ var initWebsocketConnection = function(url, onmessageFunction) {
//TODO: get the protocol from config file dependent on environment. (dev: ws, prod: wss)
//causes: Puma::HttpParserError: Invalid HTTP format, parsing fails.
//TODO: make sure that this gets cached.
websocket = new WebSocket('<%= DockerClient.config['ws_client_protocol'] %>' + window.location.hostname + ':' + window.location.port + url);
websocket.onopen = function(evt) { resetOutputTab(); }; // todo show some kind of indicator for established connection
websocket.onclose = function(evt) { /* expected at some point */ };
- websocket.onmessage = function(evt) { parseCanvasMessage(evt.data, true); };
+ websocket.onmessage = onmessageFunction;
websocket.onerror = function(evt) { showWebsocketError(); };
websocket.flush = function() { this.send('\n'); }
};
diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb
index 4f9d6a5b..c656ea87 100644
--- a/app/controllers/submissions_controller.rb
+++ b/app/controllers/submissions_controller.rb
@@ -214,7 +214,11 @@ class SubmissionsController < ApplicationController
end
def score
- render(json: score_submission(@submission))
+ hijack do |tubesock|
+ Thread.new { EventMachine.run } unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive?
+ # tubesock is the socket to the client
+ tubesock.send_data JSON.dump(score_submission(@submission))
+ end
end
def set_docker_client
From 7c1be5594a72d210997fb2757ef3448712cbbe55 Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Fri, 17 Jun 2016 17:23:47 +0200
Subject: [PATCH 44/81] also handle testcommand via websocket
---
app/assets/javascripts/editor.js.erb | 11 ++++++-----
app/controllers/submissions_controller.rb | 10 ++++++++--
2 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb
index f9555e92..dc79ccff 100644
--- a/app/assets/javascripts/editor.js.erb
+++ b/app/assets/javascripts/editor.js.erb
@@ -350,13 +350,14 @@ $(function() {
flowrOutputBuffer = '';
};
- var handleTestResponse = function(response) {
+ var handleTestResponse = function(websocket_event) {
+ result = JSON.parse(websocket_event.data);
clearOutput();
- printOutput(response[0], false, 0);
+ printOutput(result, false, 0);
if (qa_api) {
- qa_api.executeCommand('syncOutput', [response]);
+ qa_api.executeCommand('syncOutput', [result]);
}
- showStatus(response[0]);
+ showStatus(result);
showTab(1);
};
@@ -956,7 +957,7 @@ $(function() {
createSubmission(this, null, function(response) {
showSpinner($('#test'));
var url = response.test_url.replace(FILENAME_URL_PLACEHOLDER, active_file.filename);
- evaluateCode(url, false, handleTestResponse);
+ evaluateCode(url, true, handleTestResponse);
});
}
};
diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb
index c656ea87..335e4b0c 100644
--- a/app/controllers/submissions_controller.rb
+++ b/app/controllers/submissions_controller.rb
@@ -270,8 +270,14 @@ class SubmissionsController < ApplicationController
private :store_error
def test
- output = @docker_client.execute_test_command(@submission, params[:filename])
- render(json: [output])
+ hijack do |tubesock|
+ Thread.new { EventMachine.run } unless EventMachine.reactor_running? && EventMachine.reactor_thread.alive?
+
+ output = @docker_client.execute_test_command(@submission, params[:filename])
+
+ # tubesock is the socket to the client
+ tubesock.send_data JSON.dump(output)
+ end
end
def with_server_sent_events
From d29cf9cf6134691cdeba974499d4979b46521848 Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Fri, 17 Jun 2016 19:22:25 +0200
Subject: [PATCH 45/81] Also support run output for QaApi
---
app/assets/javascripts/editor.js.erb | 15 +++++++++++++++
lib/docker_client.rb | 2 +-
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb
index dc79ccff..f9ab5b94 100644
--- a/app/assets/javascripts/editor.js.erb
+++ b/app/assets/javascripts/editor.js.erb
@@ -37,6 +37,7 @@ $(function() {
var ENTER_KEY_CODE = 13;
var flowrOutputBuffer = "";
+ var QaApiOutputBuffer = {'stdout': '', 'stderr': ''};
var flowrResultHtml = ''
var ajax = function(options) {
@@ -317,6 +318,14 @@ $(function() {
showTab(2);
};
+ var handleQaApiOutput = function() {
+ if (qa_api) {
+ qa_api.executeCommand('syncOutput', [[QaApiOutputBuffer]]);
+ // reset the object
+ }
+ QaApiOutputBuffer = {'stdout': '', 'stderr': ''};
+ }
+
// activate flowr only for half of the audience
var isFlowrEnabled = true;//parseInt($('#editor').data('user-id'))%2 == 0;
var handleStderrOutputForFlowr = function() {
@@ -586,10 +595,15 @@ $(function() {
} else if (output.stderr) {
element.addClass('text-warning').append(output.stderr);
+ flowrOutputBuffer += output.stderr;
+ QaApiOutputBuffer.stderr += output.stderr;
} else if (output.stdout) {
//if (output_mode_is_streaming){
element.addClass('text-success').append(output.stdout);
flowrOutputBuffer += output.stdout;
+ QaApiOutputBuffer.stdout += output.stdout;
+
+
//}else{
// element.addClass('text-success');
// element.data('content_buffer' , element.data('content_buffer') + output.stdout);
@@ -1037,6 +1051,7 @@ $(function() {
break;
case 'exit':
killWebsocketAndContainer();
+ handleQaApiOutput();
handleStderrOutputForFlowr();
break;
case 'timeout':
diff --git a/lib/docker_client.rb b/lib/docker_client.rb
index 80986377..f993c37c 100644
--- a/lib/docker_client.rb
+++ b/lib/docker_client.rb
@@ -200,7 +200,7 @@ class DockerClient
execute_command(command, nil, block)
end
- #only used by server sent events (deprecated?)
+ #only used by score
def execute_command(command, before_execution_block, output_consuming_block)
#tries ||= 0
@container = DockerContainerPool.get_container(@execution_environment)
From c21bf3f3d3aeb4a2d4130886e644e7e69d071249 Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Fri, 17 Jun 2016 19:24:04 +0200
Subject: [PATCH 46/81] Adapt Modernizr requires.. We no longer need
eventsource
---
app/assets/javascripts/editor.js.erb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/app/assets/javascripts/editor.js.erb b/app/assets/javascripts/editor.js.erb
index f9ab5b94..c00d7350 100644
--- a/app/assets/javascripts/editor.js.erb
+++ b/app/assets/javascripts/editor.js.erb
@@ -538,8 +538,8 @@ $(function() {
};
var isBrowserSupported = function() {
- // eventsource tests for server send events (used for scoring), websockets is used for run
- return Modernizr.eventsource && Modernizr.websockets;
+ // websockets is used for run, score and test
+ return Modernizr.websockets;
};
var populatePanel = function(panel, result, index) {
From 918da5270dddb74fd9b985ef7f18547f4b8c5d5c Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Wed, 22 Jun 2016 13:06:35 +0200
Subject: [PATCH 47/81] added id for h4 holding the rfc-id updated locales.
---
app/views/request_for_comments/show.html.erb | 4 ++--
config/locales/de.yml | 2 ++
config/locales/en.yml | 3 +--
3 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/app/views/request_for_comments/show.html.erb b/app/views/request_for_comments/show.html.erb
index 1d6bb54c..3f353e32 100644
--- a/app/views/request_for_comments/show.html.erb
+++ b/app/views/request_for_comments/show.html.erb
@@ -1,5 +1,5 @@
-
<%= Exercise.find(@request_for_comment.exercise_id) %>
+
<%= Exercise.find(@request_for_comment.exercise_id) %>
<%
user = @request_for_comment.user
@@ -102,7 +102,7 @@ do not put a carriage return in the line below. it will be present in the presen
row: row,
column: 0,
text: commenttext,
- request_id: $('h4').data('rfc-id')
+ request_id: $('h4#exercise_caption').data('rfc-id')
}
},
dataType: 'json',
diff --git a/config/locales/de.yml b/config/locales/de.yml
index a3b580b5..a4d69694 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -331,6 +331,8 @@ de:
es gibt einen neuen Kommentar von %{commenting_user_displayname} zu Ihrer Kommentaranfrage auf CodeOcean.
Sie finden ihn hier: %{link}
+
+ Diese Mail wurde automatisch von CodeOcean verschickt.
subject: Sie haben einen neuen Kommentar von %{commenting_user_displayname} auf CodeOcean erhalten.
reset_password:
body: 'Bitte besuchen Sie %{link}, sofern Sie Ihr Passwort zurücksetzen wollen.'
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 1162971d..28344446 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -332,8 +332,7 @@ en:
you received a new comment from %{commenting_user_displayname} to your request for comments on CodeOcean.
You can find it here: %{link}
- Best regards,
- your Teaching Team
+ This mail was automatically sent by CodeOcean.
subject: 'You received a new comment on CodeOcean from %{commenting_user_displayname}.'
reset_password:
body: 'Please visit %{link} if you want to reset your password.'
From 83cf3b23212fcf78f3953a9dbb3697cc5dbac6c6 Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Wed, 22 Jun 2016 14:16:23 +0200
Subject: [PATCH 48/81] added line breaks ( tags) in the email body.
---
config/locales/de.yml | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/config/locales/de.yml b/config/locales/de.yml
index a4d69694..32ab47ee 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -327,12 +327,12 @@ de:
subject: Bitte schließen Sie Ihre Registrierung ab.
got_new_comment:
body: |
- Hallo %{receiver_displayname},
-
+ Hallo %{receiver_displayname},
+
es gibt einen neuen Kommentar von %{commenting_user_displayname} zu Ihrer Kommentaranfrage auf CodeOcean.
- Sie finden ihn hier: %{link}
-
- Diese Mail wurde automatisch von CodeOcean verschickt.
+ Sie finden ihn hier: %{link}
+
+ Diese Mail wurde automatisch von CodeOcean verschickt.
subject: Sie haben einen neuen Kommentar von %{commenting_user_displayname} auf CodeOcean erhalten.
reset_password:
body: 'Bitte besuchen Sie %{link}, sofern Sie Ihr Passwort zurücksetzen wollen.'
From e0eac2036114a75726bb7242dc044cdcec295cff Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Wed, 22 Jun 2016 14:21:17 +0200
Subject: [PATCH 49/81] added some more line breaks to the mail bodys of mails
on new comments.
---
config/locales/de.yml | 2 +-
config/locales/en.yml | 10 +++++-----
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/config/locales/de.yml b/config/locales/de.yml
index 32ab47ee..7f0afc00 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -329,7 +329,7 @@ de:
body: |
Hallo %{receiver_displayname},
- es gibt einen neuen Kommentar von %{commenting_user_displayname} zu Ihrer Kommentaranfrage auf CodeOcean.
+ es gibt einen neuen Kommentar von %{commenting_user_displayname} zu Ihrer Kommentaranfrage auf CodeOcean.
Sie finden ihn hier: %{link}
Diese Mail wurde automatisch von CodeOcean verschickt.
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 28344446..d622ea88 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -327,11 +327,11 @@ en:
subject: Please complete your registration.
got_new_comment:
body: |
- Dear %{receiver_displayname},
-
- you received a new comment from %{commenting_user_displayname} to your request for comments on CodeOcean.
- You can find it here: %{link}
-
+ Dear %{receiver_displayname},
+
+ you received a new comment from %{commenting_user_displayname} to your request for comments on CodeOcean.
+ You can find it here: %{link}
+
This mail was automatically sent by CodeOcean.
subject: 'You received a new comment on CodeOcean from %{commenting_user_displayname}.'
reset_password:
From b7ce38996108409242e8335ca769736adcb76d51 Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Thu, 23 Jun 2016 10:47:44 +0200
Subject: [PATCH 50/81] Adapted locales so that german as well as english texts
are now sent for every new comment.
---
config/locales/de.yml | 12 ++++++++++++
config/locales/en.yml | 14 +++++++++++++-
2 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/config/locales/de.yml b/config/locales/de.yml
index 7f0afc00..d227e7b7 100644
--- a/config/locales/de.yml
+++ b/config/locales/de.yml
@@ -327,12 +327,24 @@ de:
subject: Bitte schließen Sie Ihre Registrierung ab.
got_new_comment:
body: |
+ English version below
+ _________________________
+
Hallo %{receiver_displayname},
es gibt einen neuen Kommentar von %{commenting_user_displayname} zu Ihrer Kommentaranfrage auf CodeOcean.
Sie finden ihn hier: %{link}
Diese Mail wurde automatisch von CodeOcean verschickt.
+
+ _________________________
+
+ Dear %{receiver_displayname},
+
+ you received a new comment from %{commenting_user_displayname} to your request for comments on CodeOcean.
+ You can find it here: %{link}
+
+ This mail was automatically sent by CodeOcean.
subject: Sie haben einen neuen Kommentar von %{commenting_user_displayname} auf CodeOcean erhalten.
reset_password:
body: 'Bitte besuchen Sie %{link}, sofern Sie Ihr Passwort zurücksetzen wollen.'
diff --git a/config/locales/en.yml b/config/locales/en.yml
index d622ea88..684a350d 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -327,12 +327,24 @@ en:
subject: Please complete your registration.
got_new_comment:
body: |
+ English version below
+ _________________________
+
+ Hallo %{receiver_displayname},
+
+ es gibt einen neuen Kommentar von %{commenting_user_displayname} zu Ihrer Kommentaranfrage auf CodeOcean.
+ Sie finden ihn hier: %{link}
+
+ Diese Mail wurde automatisch von CodeOcean verschickt.
+
+ _________________________
+
Dear %{receiver_displayname},
you received a new comment from %{commenting_user_displayname} to your request for comments on CodeOcean.
You can find it here: %{link}
- This mail was automatically sent by CodeOcean.
+ This mail was automatically sent by CodeOcean.
subject: 'You received a new comment on CodeOcean from %{commenting_user_displayname}.'
reset_password:
body: 'Please visit %{link} if you want to reset your password.'
From bd6d4c4d71987ecee9dd7d7237975399a1e27378 Mon Sep 17 00:00:00 2001
From: Ralf Teusner
Date: Thu, 23 Jun 2016 14:23:28 +0200
Subject: [PATCH 51/81] Syntax Highlighting for the Request for Comment View
---
app/views/request_for_comments/show.html.erb | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/app/views/request_for_comments/show.html.erb b/app/views/request_for_comments/show.html.erb
index 3f353e32..a1ffb5ff 100644
--- a/app/views/request_for_comments/show.html.erb
+++ b/app/views/request_for_comments/show.html.erb
@@ -25,22 +25,32 @@
<% submission.files.each do |file| %>
<%= (file.path or "") + "/" + file.name + file.file_type.file_extension %>
-