From d5121cab07b9f63922db23c296a66c32bf2ba338 Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Wed, 13 Sep 2017 13:28:31 +0200 Subject: [PATCH 01/15] add cause to testruns trigger run and assess on request_for_comment --- .../editor/participantsupport.js.erb | 4 +-- .../javascripts/editor/submissions.js.erb | 28 ++++++++++--------- app/assets/stylesheets/statistics.css.scss | 8 ++++++ .../concerns/submission_scoring.rb | 2 +- .../request_for_comments_controller.rb | 5 ++++ app/controllers/submissions_controller.rb | 2 +- .../external_users/statistics.html.slim | 4 ++- .../20170830083601_add_cause_to_testruns.rb | 18 ++++++++++++ 8 files changed, 53 insertions(+), 18 deletions(-) create mode 100644 db/migrate/20170830083601_add_cause_to_testruns.rb diff --git a/app/assets/javascripts/editor/participantsupport.js.erb b/app/assets/javascripts/editor/participantsupport.js.erb index 91e9f0d1..63787f4a 100644 --- a/app/assets/javascripts/editor/participantsupport.js.erb +++ b/app/assets/javascripts/editor/participantsupport.js.erb @@ -59,8 +59,6 @@ CodeOceanEditorCodePilot = { } }; -//Request for comments does currently not work on staging platform (no relative root_url used here). -//To fix this rely on ruby routes CodeOceanEditorRequestForComments = { requestComments: function () { var user_id = $('#editor').data('user-id'); @@ -83,6 +81,8 @@ CodeOceanEditorRequestForComments = { }).done(function () { this.hideSpinner(); $.flash.success({text: $('#askForCommentsButton').data('message-success')}); + // trigger a run + this.runSubmission.call(this, submission); }.bind(this)).error(this.ajaxError.bind(this)); }; diff --git a/app/assets/javascripts/editor/submissions.js.erb b/app/assets/javascripts/editor/submissions.js.erb index 20d8cd10..21250f7e 100644 --- a/app/assets/javascripts/editor/submissions.js.erb +++ b/app/assets/javascripts/editor/submissions.js.erb @@ -142,19 +142,21 @@ CodeOceanEditorSubmissions = { * Execution-Logic */ runCode: function(event) { - event.preventDefault(); - if ($('#run').is(':visible')) { - this.createSubmission('#run', null, function(response) { - //Run part starts here - $('#stop').data('url', response.stop_url); - this.running = true; - this.showSpinner($('#run')); - $('#score_div').addClass('hidden'); - this.toggleButtonStates(); - var url = response.run_url.replace(this.FILENAME_URL_PLACEHOLDER, this.active_file.filename.replace(/#$/,'')); // remove # if it is the last character, this is not part of the filename and just an anchor - this.initializeSocketForRunning(url); - }.bind(this)); - } + event.preventDefault(); + if ($('#run').is(':visible')) { + this.createSubmission('#run', null, this.runSubmission.bind(this)); + } + }, + + runSubmission: function (submission) { + //Run part starts here + $('#stop').data('url', submission.stop_url); + this.running = true; + this.showSpinner($('#run')); + $('#score_div').addClass('hidden'); + this.toggleButtonStates(); + var url = submission.run_url.replace(this.FILENAME_URL_PLACEHOLDER, this.active_file.filename.replace(/#$/,'')); // remove # if it is the last character, this is not part of the filename and just an anchor + this.initializeSocketForRunning(url); }, saveCode: function(event) { diff --git a/app/assets/stylesheets/statistics.css.scss b/app/assets/stylesheets/statistics.css.scss index f656cd9a..a5ea4430 100644 --- a/app/assets/stylesheets/statistics.css.scss +++ b/app/assets/stylesheets/statistics.css.scss @@ -42,6 +42,14 @@ div.positive-result { box-shadow: 0px 0px 11px 1px rgba(44,222,0,1); } +div.unknown-result { + border-radius: 50%; + background-color: #ffca00; + -webkit-box-shadow: 0px 0px 11px 1px rgb(255, 202, 0); + -moz-box-shadow: 0px 0px 11px 1px rgb(255, 202, 0); + box-shadow: 0px 0px 11px 1px rgb(255, 202, 0); +} + div.negative-result { border-radius: 50%; background-color: #ff2600; diff --git a/app/controllers/concerns/submission_scoring.rb b/app/controllers/concerns/submission_scoring.rb index 16f1f061..41f9ff26 100644 --- a/app/controllers/concerns/submission_scoring.rb +++ b/app/controllers/concerns/submission_scoring.rb @@ -9,7 +9,7 @@ module SubmissionScoring assessment = assessor.assess(output) passed = ((assessment[:passed] == assessment[:count]) and (assessment[:score] > 0)) testrun_output = passed ? nil : output[:stderr] - Testrun.new(submission: submission, file: file, passed: passed, output: testrun_output).save + Testrun.new(submission: submission, cause: 'assess', file: file, passed: passed, output: testrun_output).save output.merge!(assessment) output.merge!(filename: file.name_with_extension, message: feedback_message(file, output[:score]), weight: file.weight) end diff --git a/app/controllers/request_for_comments_controller.rb b/app/controllers/request_for_comments_controller.rb index fca5c99b..6e587c73 100644 --- a/app/controllers/request_for_comments_controller.rb +++ b/app/controllers/request_for_comments_controller.rb @@ -1,4 +1,5 @@ class RequestForCommentsController < ApplicationController + include SubmissionScoring before_action :set_request_for_comment, only: [:show, :edit, :update, :destroy, :mark_as_solved, :set_thank_you_note] skip_after_action :verify_authorized @@ -110,6 +111,10 @@ class RequestForCommentsController < ApplicationController @request_for_comment = RequestForComment.new(request_for_comment_params) respond_to do |format| if @request_for_comment.save + # create thread here and execute tests. A run is triggered from the frontend and does not need to be handled here. + Thread.new do + score_submission(@request_for_comment.submission) + end format.json { render :show, status: :created, location: @request_for_comment } else format.html { render :new } diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 9b37fde0..52baefe1 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -262,7 +262,7 @@ class SubmissionsController < ApplicationController def save_run_output if !@message_buffer.blank? @message_buffer = @message_buffer[(0..max_message_buffer_size-1)] # trim the string to max_message_buffer_size chars - Testrun.create(file: @file, submission: @submission, output: @message_buffer) + Testrun.create(file: @file, cause: 'run', submission: @submission, output: @message_buffer) end end diff --git a/app/views/exercises/external_users/statistics.html.slim b/app/views/exercises/external_users/statistics.html.slim index 313a19b0..8b5c3b30 100644 --- a/app/views/exercises/external_users/statistics.html.slim +++ b/app/views/exercises/external_users/statistics.html.slim @@ -54,8 +54,10 @@ h1 = "#{@exercise} (external user #{@external_user})" -submission_or_intervention.testruns.each do |run| - if run.passed .unit-test-result.positive-result title=run.output - - else + - elsif run.failed .unit-test-result.negative-result title=run.output + - else + .unit-test-result.unknown-result title=run.output td = Time.at(deltas[1..index].inject(:+)).utc.strftime("%H:%M:%S") if index > 0 -working_times_until.push((Time.at(deltas[1..index].inject(:+)).utc.strftime("%H:%M:%S") if index > 0)) - elsif submission_or_intervention.is_a? UserExerciseIntervention diff --git a/db/migrate/20170830083601_add_cause_to_testruns.rb b/db/migrate/20170830083601_add_cause_to_testruns.rb new file mode 100644 index 00000000..f9a859c4 --- /dev/null +++ b/db/migrate/20170830083601_add_cause_to_testruns.rb @@ -0,0 +1,18 @@ +class AddCauseToTestruns < ActiveRecord::Migration + def up + add_column :testruns, :cause, :string + Testrun.reset_column_information + Testrun.all.each{ |testrun| + if(testrun.submission.nil?) + say_with_time "#{testrun.id} has no submission" do end + else + testrun.cause = testrun.submission.cause + testrun.save + end + } + end + + def down + remove_column :testruns, :cause + end +end From ae1e465d1fb08d3f7d51b6500ee95b5afb06e5ec Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Wed, 13 Sep 2017 13:28:31 +0200 Subject: [PATCH 02/15] add cause to testruns trigger run and assess on request_for_comment --- .../editor/participantsupport.js.erb | 4 +-- .../javascripts/editor/submissions.js.erb | 28 ++++++++++--------- app/assets/stylesheets/statistics.css.scss | 8 ++++++ .../concerns/submission_scoring.rb | 2 +- .../request_for_comments_controller.rb | 5 ++++ app/controllers/submissions_controller.rb | 2 +- .../external_users/statistics.html.slim | 4 ++- .../20170830083601_add_cause_to_testruns.rb | 18 ++++++++++++ 8 files changed, 53 insertions(+), 18 deletions(-) create mode 100644 db/migrate/20170830083601_add_cause_to_testruns.rb diff --git a/app/assets/javascripts/editor/participantsupport.js.erb b/app/assets/javascripts/editor/participantsupport.js.erb index 91e9f0d1..63787f4a 100644 --- a/app/assets/javascripts/editor/participantsupport.js.erb +++ b/app/assets/javascripts/editor/participantsupport.js.erb @@ -59,8 +59,6 @@ CodeOceanEditorCodePilot = { } }; -//Request for comments does currently not work on staging platform (no relative root_url used here). -//To fix this rely on ruby routes CodeOceanEditorRequestForComments = { requestComments: function () { var user_id = $('#editor').data('user-id'); @@ -83,6 +81,8 @@ CodeOceanEditorRequestForComments = { }).done(function () { this.hideSpinner(); $.flash.success({text: $('#askForCommentsButton').data('message-success')}); + // trigger a run + this.runSubmission.call(this, submission); }.bind(this)).error(this.ajaxError.bind(this)); }; diff --git a/app/assets/javascripts/editor/submissions.js.erb b/app/assets/javascripts/editor/submissions.js.erb index 20d8cd10..21250f7e 100644 --- a/app/assets/javascripts/editor/submissions.js.erb +++ b/app/assets/javascripts/editor/submissions.js.erb @@ -142,19 +142,21 @@ CodeOceanEditorSubmissions = { * Execution-Logic */ runCode: function(event) { - event.preventDefault(); - if ($('#run').is(':visible')) { - this.createSubmission('#run', null, function(response) { - //Run part starts here - $('#stop').data('url', response.stop_url); - this.running = true; - this.showSpinner($('#run')); - $('#score_div').addClass('hidden'); - this.toggleButtonStates(); - var url = response.run_url.replace(this.FILENAME_URL_PLACEHOLDER, this.active_file.filename.replace(/#$/,'')); // remove # if it is the last character, this is not part of the filename and just an anchor - this.initializeSocketForRunning(url); - }.bind(this)); - } + event.preventDefault(); + if ($('#run').is(':visible')) { + this.createSubmission('#run', null, this.runSubmission.bind(this)); + } + }, + + runSubmission: function (submission) { + //Run part starts here + $('#stop').data('url', submission.stop_url); + this.running = true; + this.showSpinner($('#run')); + $('#score_div').addClass('hidden'); + this.toggleButtonStates(); + var url = submission.run_url.replace(this.FILENAME_URL_PLACEHOLDER, this.active_file.filename.replace(/#$/,'')); // remove # if it is the last character, this is not part of the filename and just an anchor + this.initializeSocketForRunning(url); }, saveCode: function(event) { diff --git a/app/assets/stylesheets/statistics.css.scss b/app/assets/stylesheets/statistics.css.scss index f656cd9a..a5ea4430 100644 --- a/app/assets/stylesheets/statistics.css.scss +++ b/app/assets/stylesheets/statistics.css.scss @@ -42,6 +42,14 @@ div.positive-result { box-shadow: 0px 0px 11px 1px rgba(44,222,0,1); } +div.unknown-result { + border-radius: 50%; + background-color: #ffca00; + -webkit-box-shadow: 0px 0px 11px 1px rgb(255, 202, 0); + -moz-box-shadow: 0px 0px 11px 1px rgb(255, 202, 0); + box-shadow: 0px 0px 11px 1px rgb(255, 202, 0); +} + div.negative-result { border-radius: 50%; background-color: #ff2600; diff --git a/app/controllers/concerns/submission_scoring.rb b/app/controllers/concerns/submission_scoring.rb index 16f1f061..41f9ff26 100644 --- a/app/controllers/concerns/submission_scoring.rb +++ b/app/controllers/concerns/submission_scoring.rb @@ -9,7 +9,7 @@ module SubmissionScoring assessment = assessor.assess(output) passed = ((assessment[:passed] == assessment[:count]) and (assessment[:score] > 0)) testrun_output = passed ? nil : output[:stderr] - Testrun.new(submission: submission, file: file, passed: passed, output: testrun_output).save + Testrun.new(submission: submission, cause: 'assess', file: file, passed: passed, output: testrun_output).save output.merge!(assessment) output.merge!(filename: file.name_with_extension, message: feedback_message(file, output[:score]), weight: file.weight) end diff --git a/app/controllers/request_for_comments_controller.rb b/app/controllers/request_for_comments_controller.rb index 20d77bea..6057f647 100644 --- a/app/controllers/request_for_comments_controller.rb +++ b/app/controllers/request_for_comments_controller.rb @@ -1,4 +1,5 @@ class RequestForCommentsController < ApplicationController + include SubmissionScoring before_action :set_request_for_comment, only: [:show, :edit, :update, :destroy, :mark_as_solved, :set_thank_you_note] skip_after_action :verify_authorized @@ -110,6 +111,10 @@ class RequestForCommentsController < ApplicationController @request_for_comment = RequestForComment.new(request_for_comment_params) respond_to do |format| if @request_for_comment.save + # create thread here and execute tests. A run is triggered from the frontend and does not need to be handled here. + Thread.new do + score_submission(@request_for_comment.submission) + end format.json { render :show, status: :created, location: @request_for_comment } else format.html { render :new } diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 9b37fde0..52baefe1 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -262,7 +262,7 @@ class SubmissionsController < ApplicationController def save_run_output if !@message_buffer.blank? @message_buffer = @message_buffer[(0..max_message_buffer_size-1)] # trim the string to max_message_buffer_size chars - Testrun.create(file: @file, submission: @submission, output: @message_buffer) + Testrun.create(file: @file, cause: 'run', submission: @submission, output: @message_buffer) end end diff --git a/app/views/exercises/external_users/statistics.html.slim b/app/views/exercises/external_users/statistics.html.slim index 313a19b0..8b5c3b30 100644 --- a/app/views/exercises/external_users/statistics.html.slim +++ b/app/views/exercises/external_users/statistics.html.slim @@ -54,8 +54,10 @@ h1 = "#{@exercise} (external user #{@external_user})" -submission_or_intervention.testruns.each do |run| - if run.passed .unit-test-result.positive-result title=run.output - - else + - elsif run.failed .unit-test-result.negative-result title=run.output + - else + .unit-test-result.unknown-result title=run.output td = Time.at(deltas[1..index].inject(:+)).utc.strftime("%H:%M:%S") if index > 0 -working_times_until.push((Time.at(deltas[1..index].inject(:+)).utc.strftime("%H:%M:%S") if index > 0)) - elsif submission_or_intervention.is_a? UserExerciseIntervention diff --git a/db/migrate/20170830083601_add_cause_to_testruns.rb b/db/migrate/20170830083601_add_cause_to_testruns.rb new file mode 100644 index 00000000..f9a859c4 --- /dev/null +++ b/db/migrate/20170830083601_add_cause_to_testruns.rb @@ -0,0 +1,18 @@ +class AddCauseToTestruns < ActiveRecord::Migration + def up + add_column :testruns, :cause, :string + Testrun.reset_column_information + Testrun.all.each{ |testrun| + if(testrun.submission.nil?) + say_with_time "#{testrun.id} has no submission" do end + else + testrun.cause = testrun.submission.cause + testrun.save + end + } + end + + def down + remove_column :testruns, :cause + end +end From 44f70ea3dabc60be0709ce4ba88e85d7803debad Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Wed, 20 Sep 2017 13:10:37 +0200 Subject: [PATCH 03/15] save run outputs with cause requestComments with more content (5000 chars instead of 500). Always save full JSON content. --- app/controllers/submissions_controller.rb | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 52baefe1..4dfa182c 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -13,8 +13,12 @@ class SubmissionsController < ApplicationController before_action :set_mime_type, only: [:download_file, :render_file] skip_before_action :verify_authenticity_token, only: [:download_file, :render_file] - def max_message_buffer_size - 500 + def max_run_output_buffer_size + if(@submission.cause == 'requestComments') + 5000 + else + 500 + end end def authorize! @@ -196,7 +200,7 @@ class SubmissionsController < ApplicationController end def handle_message(message, tubesock, container) - @message_buffer ||= "" + @run_output ||= "" # Handle special commands first if (/^#exit/.match(message)) # Just call exit_container on the docker_client. @@ -205,19 +209,19 @@ class SubmissionsController < ApplicationController # kill_socket is called in the "on close handler" of the websocket to the container @docker_client.exit_container(container) elsif /^#timeout/.match(message) - @message_buffer = 'timeout: ' + @message_buffer # add information that this run timed out to the buffer + @run_output = 'timeout: ' + @run_output # add information that this run timed out to the buffer else # Filter out information about run_command, test_command, user or working directory run_command = @submission.execution_environment.run_command % command_substitutions(params[:filename]) test_command = @submission.execution_environment.test_command % command_substitutions(params[:filename]) if !(/root|workspace|#{run_command}|#{test_command}/.match(message)) - @message_buffer += message if @message_buffer.size <= max_message_buffer_size parse_message(message, 'stdout', tubesock) end end end def parse_message(message, output_stream, socket, recursive = true) + parsed = ''; begin parsed = JSON.parse(message) if(parsed.class == Hash && parsed.key?('cmd')) @@ -256,13 +260,16 @@ class SubmissionsController < ApplicationController socket.send_data JSON.dump(parsed) Rails.logger.info('parse_message sent: ' + JSON.dump(parsed)) end + ensure + # save the data that was send to the run_output if there is enough space left. this will be persisted as a testrun with cause "run" + @run_output += JSON.dump(parsed) if @run_output.size <= max_run_output_buffer_size end end def save_run_output - if !@message_buffer.blank? - @message_buffer = @message_buffer[(0..max_message_buffer_size-1)] # trim the string to max_message_buffer_size chars - Testrun.create(file: @file, cause: 'run', submission: @submission, output: @message_buffer) + if !@run_output.blank? + @run_output = @run_output[(0..max_run_output_buffer_size-1)] # trim the string to max_message_buffer_size chars + Testrun.create(file: @file, cause: 'run', submission: @submission, output: @run_output) end end From 194984a62067883779dcf62ac3d11fc165c4777e Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Wed, 13 Sep 2017 13:28:31 +0200 Subject: [PATCH 04/15] add cause to testruns trigger run and assess on request_for_comment --- .../editor/participantsupport.js.erb | 4 +-- .../javascripts/editor/submissions.js.erb | 28 ++++++++++--------- app/assets/stylesheets/statistics.css.scss | 8 ++++++ .../concerns/submission_scoring.rb | 2 +- .../request_for_comments_controller.rb | 5 ++++ app/controllers/submissions_controller.rb | 2 +- .../external_users/statistics.html.slim | 4 ++- .../20170830083601_add_cause_to_testruns.rb | 18 ++++++++++++ 8 files changed, 53 insertions(+), 18 deletions(-) create mode 100644 db/migrate/20170830083601_add_cause_to_testruns.rb diff --git a/app/assets/javascripts/editor/participantsupport.js.erb b/app/assets/javascripts/editor/participantsupport.js.erb index 91e9f0d1..63787f4a 100644 --- a/app/assets/javascripts/editor/participantsupport.js.erb +++ b/app/assets/javascripts/editor/participantsupport.js.erb @@ -59,8 +59,6 @@ CodeOceanEditorCodePilot = { } }; -//Request for comments does currently not work on staging platform (no relative root_url used here). -//To fix this rely on ruby routes CodeOceanEditorRequestForComments = { requestComments: function () { var user_id = $('#editor').data('user-id'); @@ -83,6 +81,8 @@ CodeOceanEditorRequestForComments = { }).done(function () { this.hideSpinner(); $.flash.success({text: $('#askForCommentsButton').data('message-success')}); + // trigger a run + this.runSubmission.call(this, submission); }.bind(this)).error(this.ajaxError.bind(this)); }; diff --git a/app/assets/javascripts/editor/submissions.js.erb b/app/assets/javascripts/editor/submissions.js.erb index 20d8cd10..21250f7e 100644 --- a/app/assets/javascripts/editor/submissions.js.erb +++ b/app/assets/javascripts/editor/submissions.js.erb @@ -142,19 +142,21 @@ CodeOceanEditorSubmissions = { * Execution-Logic */ runCode: function(event) { - event.preventDefault(); - if ($('#run').is(':visible')) { - this.createSubmission('#run', null, function(response) { - //Run part starts here - $('#stop').data('url', response.stop_url); - this.running = true; - this.showSpinner($('#run')); - $('#score_div').addClass('hidden'); - this.toggleButtonStates(); - var url = response.run_url.replace(this.FILENAME_URL_PLACEHOLDER, this.active_file.filename.replace(/#$/,'')); // remove # if it is the last character, this is not part of the filename and just an anchor - this.initializeSocketForRunning(url); - }.bind(this)); - } + event.preventDefault(); + if ($('#run').is(':visible')) { + this.createSubmission('#run', null, this.runSubmission.bind(this)); + } + }, + + runSubmission: function (submission) { + //Run part starts here + $('#stop').data('url', submission.stop_url); + this.running = true; + this.showSpinner($('#run')); + $('#score_div').addClass('hidden'); + this.toggleButtonStates(); + var url = submission.run_url.replace(this.FILENAME_URL_PLACEHOLDER, this.active_file.filename.replace(/#$/,'')); // remove # if it is the last character, this is not part of the filename and just an anchor + this.initializeSocketForRunning(url); }, saveCode: function(event) { diff --git a/app/assets/stylesheets/statistics.css.scss b/app/assets/stylesheets/statistics.css.scss index f656cd9a..a5ea4430 100644 --- a/app/assets/stylesheets/statistics.css.scss +++ b/app/assets/stylesheets/statistics.css.scss @@ -42,6 +42,14 @@ div.positive-result { box-shadow: 0px 0px 11px 1px rgba(44,222,0,1); } +div.unknown-result { + border-radius: 50%; + background-color: #ffca00; + -webkit-box-shadow: 0px 0px 11px 1px rgb(255, 202, 0); + -moz-box-shadow: 0px 0px 11px 1px rgb(255, 202, 0); + box-shadow: 0px 0px 11px 1px rgb(255, 202, 0); +} + div.negative-result { border-radius: 50%; background-color: #ff2600; diff --git a/app/controllers/concerns/submission_scoring.rb b/app/controllers/concerns/submission_scoring.rb index 16f1f061..41f9ff26 100644 --- a/app/controllers/concerns/submission_scoring.rb +++ b/app/controllers/concerns/submission_scoring.rb @@ -9,7 +9,7 @@ module SubmissionScoring assessment = assessor.assess(output) passed = ((assessment[:passed] == assessment[:count]) and (assessment[:score] > 0)) testrun_output = passed ? nil : output[:stderr] - Testrun.new(submission: submission, file: file, passed: passed, output: testrun_output).save + Testrun.new(submission: submission, cause: 'assess', file: file, passed: passed, output: testrun_output).save output.merge!(assessment) output.merge!(filename: file.name_with_extension, message: feedback_message(file, output[:score]), weight: file.weight) end diff --git a/app/controllers/request_for_comments_controller.rb b/app/controllers/request_for_comments_controller.rb index 8ef8f866..4fd19a92 100644 --- a/app/controllers/request_for_comments_controller.rb +++ b/app/controllers/request_for_comments_controller.rb @@ -1,4 +1,5 @@ class RequestForCommentsController < ApplicationController + include SubmissionScoring before_action :set_request_for_comment, only: [:show, :edit, :update, :destroy, :mark_as_solved, :set_thank_you_note] skip_after_action :verify_authorized @@ -107,6 +108,10 @@ class RequestForCommentsController < ApplicationController @request_for_comment = RequestForComment.new(request_for_comment_params) respond_to do |format| if @request_for_comment.save + # create thread here and execute tests. A run is triggered from the frontend and does not need to be handled here. + Thread.new do + score_submission(@request_for_comment.submission) + end format.json { render :show, status: :created, location: @request_for_comment } else format.html { render :new } diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 9b37fde0..52baefe1 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -262,7 +262,7 @@ class SubmissionsController < ApplicationController def save_run_output if !@message_buffer.blank? @message_buffer = @message_buffer[(0..max_message_buffer_size-1)] # trim the string to max_message_buffer_size chars - Testrun.create(file: @file, submission: @submission, output: @message_buffer) + Testrun.create(file: @file, cause: 'run', submission: @submission, output: @message_buffer) end end diff --git a/app/views/exercises/external_users/statistics.html.slim b/app/views/exercises/external_users/statistics.html.slim index 313a19b0..8b5c3b30 100644 --- a/app/views/exercises/external_users/statistics.html.slim +++ b/app/views/exercises/external_users/statistics.html.slim @@ -54,8 +54,10 @@ h1 = "#{@exercise} (external user #{@external_user})" -submission_or_intervention.testruns.each do |run| - if run.passed .unit-test-result.positive-result title=run.output - - else + - elsif run.failed .unit-test-result.negative-result title=run.output + - else + .unit-test-result.unknown-result title=run.output td = Time.at(deltas[1..index].inject(:+)).utc.strftime("%H:%M:%S") if index > 0 -working_times_until.push((Time.at(deltas[1..index].inject(:+)).utc.strftime("%H:%M:%S") if index > 0)) - elsif submission_or_intervention.is_a? UserExerciseIntervention diff --git a/db/migrate/20170830083601_add_cause_to_testruns.rb b/db/migrate/20170830083601_add_cause_to_testruns.rb new file mode 100644 index 00000000..f9a859c4 --- /dev/null +++ b/db/migrate/20170830083601_add_cause_to_testruns.rb @@ -0,0 +1,18 @@ +class AddCauseToTestruns < ActiveRecord::Migration + def up + add_column :testruns, :cause, :string + Testrun.reset_column_information + Testrun.all.each{ |testrun| + if(testrun.submission.nil?) + say_with_time "#{testrun.id} has no submission" do end + else + testrun.cause = testrun.submission.cause + testrun.save + end + } + end + + def down + remove_column :testruns, :cause + end +end From da4d54859c52d2fdc1910694d290c8d38566143a Mon Sep 17 00:00:00 2001 From: Ralf Teusner Date: Wed, 20 Sep 2017 13:10:37 +0200 Subject: [PATCH 05/15] save run outputs with cause requestComments with more content (5000 chars instead of 500). Always save full JSON content. --- app/controllers/submissions_controller.rb | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb index 52baefe1..4dfa182c 100644 --- a/app/controllers/submissions_controller.rb +++ b/app/controllers/submissions_controller.rb @@ -13,8 +13,12 @@ class SubmissionsController < ApplicationController before_action :set_mime_type, only: [:download_file, :render_file] skip_before_action :verify_authenticity_token, only: [:download_file, :render_file] - def max_message_buffer_size - 500 + def max_run_output_buffer_size + if(@submission.cause == 'requestComments') + 5000 + else + 500 + end end def authorize! @@ -196,7 +200,7 @@ class SubmissionsController < ApplicationController end def handle_message(message, tubesock, container) - @message_buffer ||= "" + @run_output ||= "" # Handle special commands first if (/^#exit/.match(message)) # Just call exit_container on the docker_client. @@ -205,19 +209,19 @@ class SubmissionsController < ApplicationController # kill_socket is called in the "on close handler" of the websocket to the container @docker_client.exit_container(container) elsif /^#timeout/.match(message) - @message_buffer = 'timeout: ' + @message_buffer # add information that this run timed out to the buffer + @run_output = 'timeout: ' + @run_output # add information that this run timed out to the buffer else # Filter out information about run_command, test_command, user or working directory run_command = @submission.execution_environment.run_command % command_substitutions(params[:filename]) test_command = @submission.execution_environment.test_command % command_substitutions(params[:filename]) if !(/root|workspace|#{run_command}|#{test_command}/.match(message)) - @message_buffer += message if @message_buffer.size <= max_message_buffer_size parse_message(message, 'stdout', tubesock) end end end def parse_message(message, output_stream, socket, recursive = true) + parsed = ''; begin parsed = JSON.parse(message) if(parsed.class == Hash && parsed.key?('cmd')) @@ -256,13 +260,16 @@ class SubmissionsController < ApplicationController socket.send_data JSON.dump(parsed) Rails.logger.info('parse_message sent: ' + JSON.dump(parsed)) end + ensure + # save the data that was send to the run_output if there is enough space left. this will be persisted as a testrun with cause "run" + @run_output += JSON.dump(parsed) if @run_output.size <= max_run_output_buffer_size end end def save_run_output - if !@message_buffer.blank? - @message_buffer = @message_buffer[(0..max_message_buffer_size-1)] # trim the string to max_message_buffer_size chars - Testrun.create(file: @file, cause: 'run', submission: @submission, output: @message_buffer) + if !@run_output.blank? + @run_output = @run_output[(0..max_run_output_buffer_size-1)] # trim the string to max_message_buffer_size chars + Testrun.create(file: @file, cause: 'run', submission: @submission, output: @run_output) end end From 1e71b46960db13db309636be6175e94c2e585215 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Thu, 21 Sep 2017 17:20:21 +0200 Subject: [PATCH 06/15] Update schema --- db/schema.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/db/schema.rb b/db/schema.rb index e7e0c6d6..988cd447 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -304,6 +304,7 @@ ActiveRecord::Schema.define(version: 20170920145852) do t.integer "submission_id" t.datetime "created_at" t.datetime "updated_at" + t.string "cause" end create_table "user_exercise_feedbacks", force: :cascade do |t| From 0e93a0bb2ea0cef27b8a67817cd16e2485d914d6 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Thu, 21 Sep 2017 17:36:52 +0200 Subject: [PATCH 07/15] Pull out admin menu --- .../request_for_comments/_admin_menu.html.slim | 9 +++++++++ app/views/request_for_comments/show.html.erb | 17 +++-------------- 2 files changed, 12 insertions(+), 14 deletions(-) create mode 100644 app/views/request_for_comments/_admin_menu.html.slim diff --git a/app/views/request_for_comments/_admin_menu.html.slim b/app/views/request_for_comments/_admin_menu.html.slim new file mode 100644 index 00000000..3f71b2ed --- /dev/null +++ b/app/views/request_for_comments/_admin_menu.html.slim @@ -0,0 +1,9 @@ +br +h4 Admin Menu +h5 + ul + li = link_to "User's current status of this exercise", statistics_external_user_exercise_path(id: @request_for_comment.exercise_id, external_user_id: @request_for_comment.user_id) + li = link_to "All exercises of this user", statistics_external_user_path(id: @request_for_comment.user_id) + ul + li = link_to "Implement the exercise yourself", implement_exercise_path(id: @request_for_comment.exercise_id) + li = link_to "Show the exercise", exercise_path(id: @request_for_comment.exercise_id) diff --git a/app/views/request_for_comments/show.html.erb b/app/views/request_for_comments/show.html.erb index 83741a87..3814ba21 100644 --- a/app/views/request_for_comments/show.html.erb +++ b/app/views/request_for_comments/show.html.erb @@ -44,21 +44,10 @@ <% end %> - - - <% if @current_user.admin? && user.is_a?(ExternalUser) %> -
-
-

Admin Menu

-
-
    -
  • <%= link_to "User's current status of this exercise", statistics_external_user_exercise_path(id: @request_for_comment.exercise_id, external_user_id: @request_for_comment.user_id) %>
  • -
  • <%= link_to "All exercises of this user", statistics_external_user_path(id: @request_for_comment.user_id) %>

  • -
  • <%= link_to "Implement the exercise yourself", implement_exercise_path(id: @request_for_comment.exercise_id) %>
  • -
  • <%= link_to "Show the exercise", exercise_path(id: @request_for_comment.exercise_id) %>
  • -
-
+ <% if @current_user.admin? && user.is_a?(ExternalUser) %> + <%= render('admin_menu') %> <% end %> +
<%= t('request_for_comments.howto_title') %>
<%= render_markdown(t('request_for_comments.howto')) %>
From d902a42962dc420d256bab431acb2b9f414c55d4 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Thu, 21 Sep 2017 17:41:21 +0200 Subject: [PATCH 08/15] Pull out mark as solved button --- .../_mark_as_solved.html.slim | 7 +++++++ app/views/request_for_comments/show.html.erb | 16 +--------------- 2 files changed, 8 insertions(+), 15 deletions(-) create mode 100644 app/views/request_for_comments/_mark_as_solved.html.slim diff --git a/app/views/request_for_comments/_mark_as_solved.html.slim b/app/views/request_for_comments/_mark_as_solved.html.slim new file mode 100644 index 00000000..b3df57fd --- /dev/null +++ b/app/views/request_for_comments/_mark_as_solved.html.slim @@ -0,0 +1,7 @@ +button.btn.btn-primary#mark-as-solved-button = t('request_for_comments.mark_as_solved') + +#thank-you-container + p = t('request_for_comments.write_a_thank_you_node') + textarea#thank-you-note + button.btn.btn-primary#send-thank-you-note = t('request_for_comments.send_thank_you_note') + button.btn.btn-default#cancel-thank-you-note = t('request_for_comments.cancel_thank_you_note') diff --git a/app/views/request_for_comments/show.html.erb b/app/views/request_for_comments/show.html.erb index 3814ba21..8ef7e16e 100644 --- a/app/views/request_for_comments/show.html.erb +++ b/app/views/request_for_comments/show.html.erb @@ -27,21 +27,7 @@ <% if (policy(@request_for_comment).mark_as_solved? and not @request_for_comment.solved?) %> - -
-

- <%= t('request_for_comments.write_a_thank_you_node') %> -

- - - -
+ <%= render('mark_as_solved') %> <% end %> <% if @current_user.admin? && user.is_a?(ExternalUser) %> From d94c5404aae929877786f4be7abdd8389a4281ec Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Thu, 21 Sep 2017 17:42:24 +0200 Subject: [PATCH 09/15] Clean up conditionals --- app/views/request_for_comments/show.html.erb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/request_for_comments/show.html.erb b/app/views/request_for_comments/show.html.erb index 8ef7e16e..b8a143f9 100644 --- a/app/views/request_for_comments/show.html.erb +++ b/app/views/request_for_comments/show.html.erb @@ -1,6 +1,6 @@

- <% if (@request_for_comment.solved?) %> + <% if @request_for_comment.solved? %> <% end %> <%= link_to(@request_for_comment.exercise.title, [:implement, @request_for_comment.exercise]) %> @@ -26,7 +26,7 @@ <% end %>

- <% if (policy(@request_for_comment).mark_as_solved? and not @request_for_comment.solved?) %> + <% if policy(@request_for_comment).mark_as_solved? and not @request_for_comment.solved? %> <%= render('mark_as_solved') %> <% end %> From ca040503443018b534bf5d37956d8ab02ebee8f6 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Sat, 23 Sep 2017 09:05:58 +0200 Subject: [PATCH 10/15] Display output and test results below RfC description --- .../stylesheets/request-for-comments.css.scss | 36 +++++++++++++++++++ app/views/request_for_comments/show.html.erb | 26 ++++++++++++++ config/locales/de.yml | 3 ++ config/locales/en.yml | 3 ++ 4 files changed, 68 insertions(+) diff --git a/app/assets/stylesheets/request-for-comments.css.scss b/app/assets/stylesheets/request-for-comments.css.scss index 8fb7bfea..e88ed573 100644 --- a/app/assets/stylesheets/request-for-comments.css.scss +++ b/app/assets/stylesheets/request-for-comments.css.scss @@ -151,3 +151,39 @@ input#subscribe { color: #008cba; margin-top: 10px; } + +.testrun-assess-results { + + display: flex; + + .result { + margin-right: 10px; + width: 10px; + height: 10px; + } + + .passed { + border-radius: 50%; + background-color: #8efa00; + -webkit-box-shadow: 0 0 11px 1px rgba(44,222,0,1); + -moz-box-shadow: 0 0 11px 1px rgba(44,222,0,1); + box-shadow: 0 0 11px 1px rgba(44,222,0,1); + } + + .unknown { + border-radius: 50%; + background-color: #ffca00; + -webkit-box-shadow: 0 0 11px 1px rgb(255, 202, 0); + -moz-box-shadow: 0 0 11px 1px rgb(255, 202, 0); + box-shadow: 0 0 11px 1px rgb(255, 202, 0); + } + + .failed { + border-radius: 50%; + background-color: #ff2600; + -webkit-box-shadow: 0 0 11px 1px rgba(222,0,0,1); + -moz-box-shadow: 0 0 11px 1px rgba(222,0,0,1); + box-shadow: 0 0 11px 1px rgba(222,0,0,1); + } + +} diff --git a/app/views/request_for_comments/show.html.erb b/app/views/request_for_comments/show.html.erb index b8a143f9..156543c1 100644 --- a/app/views/request_for_comments/show.html.erb +++ b/app/views/request_for_comments/show.html.erb @@ -9,6 +9,7 @@ <% user = @request_for_comment.user submission = @request_for_comment.submission + testruns = Testrun.where(:submission_id => @request_for_comment.submission) %> <%= user.displayname %> | <%= @request_for_comment.created_at.localtime %> @@ -37,6 +38,31 @@
<%= t('request_for_comments.howto_title') %>
<%= render_markdown(t('request_for_comments.howto')) %>
+ + + <% if testruns.size > 0 %> +
+ <% output_runs = testruns.select { |run| run.cause == 'run' } %> + <% if output_runs.size > 0 %> +
<%= t('request_for_comments.runtime_output') %>
+
+ <% output_runs.each do |testrun| %> +

<%= testrun.try(:message) or t('request_for_comments.no_output') %>

+ <% end %> +
+ <% end %> + + <% assess_runs = testruns.select { |run| run.cause == 'assess' } %> + <% if assess_runs.size > 0 %> +
<%= t('request_for_comments.test_results') %>
+
+ <% assess_runs.each do |testrun| %> +
+ <% end %> +
+ <% end %> +
+ <% end %>

diff --git a/config/locales/de.yml b/config/locales/de.yml index 62fc76b5..88a3b1c0 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -514,6 +514,9 @@ de: modal_title: "Einen Kommentar in Zeile ${line} hinzufügen" click_for_more_comments: "Klicken um ${numComments} weitere Kommentare zu sehen..." subscribe_to_author: "Bei neuen Kommentaren des Autors per E-Mail benachrichtigt werden" + no_output: "Keine Ausgabe." + runtime_output: "Programmausgabe" + test_results: "Testergebnisse" sessions: create: failure: Fehlerhafte E-Mail oder Passwort. diff --git a/config/locales/en.yml b/config/locales/en.yml index 1e13f929..5d9b78d8 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -514,6 +514,9 @@ en: modal_title: "Add a comment to line ${line}" click_for_more_comments: "Click to view ${numComments} more comments..." subscribe_to_author: "Receive E-Mail notifications for new comments of the original author" + no_output: "No output." + runtime_output: "Runtime Output" + test_results: "Test Results" sessions: create: failure: Invalid email or password. From d119ef6a38ad09c3c29fa0de8a078268ffe1377d Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Sat, 23 Sep 2017 09:10:26 +0200 Subject: [PATCH 11/15] Fix message name --- 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 156543c1..78f9accc 100644 --- a/app/views/request_for_comments/show.html.erb +++ b/app/views/request_for_comments/show.html.erb @@ -47,7 +47,7 @@
<%= t('request_for_comments.runtime_output') %>
<% output_runs.each do |testrun| %> -

<%= testrun.try(:message) or t('request_for_comments.no_output') %>

+

<%= testrun.try(:output) or t('request_for_comments.no_output') %>

<% end %>
<% end %> From 7a0c7389d4402635b593113cfc74a57d7e491a49 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Sun, 24 Sep 2017 11:15:05 +0200 Subject: [PATCH 12/15] Refactor RfC UI; decouple style from structure --- .../stylesheets/request-for-comments.css.scss | 22 ++++ app/views/request_for_comments/show.html.erb | 108 ++++++++++-------- 2 files changed, 82 insertions(+), 48 deletions(-) diff --git a/app/assets/stylesheets/request-for-comments.css.scss b/app/assets/stylesheets/request-for-comments.css.scss index e88ed573..a0418e48 100644 --- a/app/assets/stylesheets/request-for-comments.css.scss +++ b/app/assets/stylesheets/request-for-comments.css.scss @@ -152,6 +152,28 @@ input#subscribe { margin-top: 10px; } +.rfc { + + h5 { + text-decoration: underline; + } + + .text { + font-size: larger; + } + + .question { + display: flex; + align-items: baseline; + + .text { + margin-left: 10px; + } + + } + +} + .testrun-assess-results { display: flex; diff --git a/app/views/request_for_comments/show.html.erb b/app/views/request_for_comments/show.html.erb index 78f9accc..0fbeef37 100644 --- a/app/views/request_for_comments/show.html.erb +++ b/app/views/request_for_comments/show.html.erb @@ -14,55 +14,67 @@ <%= user.displayname %> | <%= @request_for_comment.created_at.localtime %>

- -
- <%= t('activerecord.attributes.exercise.description') %>: <%= render_markdown(@request_for_comment.exercise.description) %> -
- -
- <% if @request_for_comment.question and not @request_for_comment.question == '' %> - <%= t('activerecord.attributes.request_for_comments.question')%>: "<%= @request_for_comment.question %>" - <% else %> - <%= t('activerecord.attributes.request_for_comments.question')%>: <%= t('request_for_comments.no_question') %> - <% end %> -
- - <% if policy(@request_for_comment).mark_as_solved? and not @request_for_comment.solved? %> - <%= render('mark_as_solved') %> - <% end %> - - <% if @current_user.admin? && user.is_a?(ExternalUser) %> - <%= render('admin_menu') %> - <% end %> - -
- <%= t('request_for_comments.howto_title') %>
<%= render_markdown(t('request_for_comments.howto')) %> -
- - - <% if testruns.size > 0 %> -
- <% output_runs = testruns.select { |run| run.cause == 'run' } %> - <% if output_runs.size > 0 %> -
<%= t('request_for_comments.runtime_output') %>
-
- <% output_runs.each do |testrun| %> -

<%= testrun.try(:output) or t('request_for_comments.no_output') %>

- <% end %> -
- <% end %> - - <% assess_runs = testruns.select { |run| run.cause == 'assess' } %> - <% if assess_runs.size > 0 %> -
<%= t('request_for_comments.test_results') %>
-
- <% assess_runs.each do |testrun| %> -
- <% end %> -
- <% end %> +
+
+
+ <%= t('activerecord.attributes.exercise.description') %>: +
+
+ <%= render_markdown(@request_for_comment.exercise.description) %> +
- <% end %> + +
+
+ <%= t('activerecord.attributes.request_for_comments.question')%>: +
+
+ <%= @request_for_comment.question or t('request_for_comments.no_question')%> +
+
+ + <% if policy(@request_for_comment).mark_as_solved? and not @request_for_comment.solved? %> + <%= render('mark_as_solved') %> + <% end %> + + <% if @current_user.admin? && user.is_a?(ExternalUser) %> + <%= render('admin_menu') %> + <% end %> + +
+
+ <%= t('request_for_comments.howto_title') %> +
+
+ <%= render_markdown(t('request_for_comments.howto')) %> +
+
+ + + <% if testruns.size > 0 %> +
+ <% output_runs = testruns.select { |run| run.cause == 'run' } %> + <% if output_runs.size > 0 %> +
<%= t('request_for_comments.runtime_output') %>
+
+ <% output_runs.each do |testrun| %> +

<%= testrun.try(:output) or t('request_for_comments.no_output') %>

+ <% end %> +
+ <% end %> + + <% assess_runs = testruns.select { |run| run.cause == 'assess' } %> + <% if assess_runs.size > 0 %> +
<%= t('request_for_comments.test_results') %>
+
+ <% assess_runs.each do |testrun| %> +
+ <% end %> +
+ <% end %> +
+ <% end %> +

From 5498269aec22841e406a74b55e4e2dd2ced759c3 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Wed, 27 Sep 2017 10:21:43 +0200 Subject: [PATCH 13/15] Reorder RfC description --- app/views/request_for_comments/show.html.erb | 29 ++++++++++---------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/app/views/request_for_comments/show.html.erb b/app/views/request_for_comments/show.html.erb index 0fbeef37..4ac65629 100644 --- a/app/views/request_for_comments/show.html.erb +++ b/app/views/request_for_comments/show.html.erb @@ -37,19 +37,6 @@ <%= render('mark_as_solved') %> <% end %> - <% if @current_user.admin? && user.is_a?(ExternalUser) %> - <%= render('admin_menu') %> - <% end %> - -
-
- <%= t('request_for_comments.howto_title') %> -
-
- <%= render_markdown(t('request_for_comments.howto')) %> -
-
- <% if testruns.size > 0 %>
@@ -74,9 +61,23 @@ <% end %>
<% end %> + + <% if @current_user.admin? && user.is_a?(ExternalUser) %> + <%= render('admin_menu') %> + <% end %> + +
+ +
+
+ <%= t('request_for_comments.howto_title') %> +
+
+ <%= render_markdown(t('request_for_comments.howto')) %> +
+
-
<% if testruns.size > 0 %> -
+
<% output_runs = testruns.select { |run| run.cause == 'run' } %> <% if output_runs.size > 0 %>
<%= t('request_for_comments.runtime_output') %>
+ <% output_runs.each do |testrun| %> -

<%= testrun.try(:output) or t('request_for_comments.no_output') %>

+
<%= testrun.try(:output) or t('request_for_comments.no_output') %>
<% end %>
<% end %> @@ -142,6 +143,12 @@ also, all settings from the rails model needed for the editor configuration in t thankYouContainer.hide(); }); + $('.text > .collapse-button').on('click', function(e) { + $(this).toggleClass('fa-chevron-down'); + $(this).toggleClass('fa-chevron-up'); + $(this).parent().toggleClass('collapsed'); + }); + // set file paths for ace var ACE_FILES_PATH = '/assets/ace/'; _.each(['modePath', 'themePath', 'workerPath'], function(attribute) { diff --git a/config/locales/de.yml b/config/locales/de.yml index 88a3b1c0..f2a080de 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -494,7 +494,7 @@ de: Um Kommentare zu einer Programmzeile hinzuzufügen, kann einfach auf die jeweilige Zeilennummer auf der linken Seite geklickt werden.
Es öffnet sich ein Textfeld, in dem der Kommentar eingetragen werden kann.
Mit "Kommentar abschicken" wird der Kommentar dann gesichert und taucht als Sprechblase neben der Zeile auf. - howto_title: 'Anleitung:' + howto_title: 'Anleitung' index: get_my_comment_requests: Meine Kommentaranfragen all: "Alle Kommentaranfragen" diff --git a/config/locales/en.yml b/config/locales/en.yml index 5d9b78d8..0542bfd4 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -494,7 +494,7 @@ en: To leave comments to a specific code line, click on the respective line number.
Enter your comment in the popup and save it by clicking "Comment this".
Your comment will show up next to the line number as a speech bubble symbol. - howto_title: 'How to comment:' + howto_title: 'How to comment' index: all: All Requests for Comments get_my_comment_requests: My Requests for Comments From 54f312dfd395b4cbf8fc4ad405288d7cd3970dba Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Wed, 27 Sep 2017 15:04:52 +0200 Subject: [PATCH 15/15] Remove comment --- app/views/request_for_comments/show.html.erb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/views/request_for_comments/show.html.erb b/app/views/request_for_comments/show.html.erb index a95970f6..eb88caf1 100644 --- a/app/views/request_for_comments/show.html.erb +++ b/app/views/request_for_comments/show.html.erb @@ -36,8 +36,7 @@ <% if policy(@request_for_comment).mark_as_solved? and not @request_for_comment.solved? %> <%= render('mark_as_solved') %> <% end %> - - + <% if testruns.size > 0 %>
<% output_runs = testruns.select { |run| run.cause == 'run' } %>