Merge pull request #117 from openHPI/ImproveUserfeedback
added user feedback page after submission of scores
This commit is contained in:
@ -380,8 +380,12 @@ class ExercisesController < ApplicationController
|
||||
if @submission.normalized_score == 1.0
|
||||
# if user is external and has an own rfc, redirect to it and message him to clean up and accept the answer. (we need to check that the user is external,
|
||||
# otherwise an internal user could be shown a false rfc here, since current_user.id is polymorphic, but only makes sense for external users when used with rfcs.)
|
||||
# redirect 10 percent pseudorandomly to the feedback page
|
||||
if current_user.respond_to? :external_id
|
||||
if rfc = RequestForComment.unsolved.where(exercise_id: @submission.exercise, user_id: current_user.id).first
|
||||
if ((current_user.id + @submission.exercise.created_at.to_i) % 10 == 1)
|
||||
redirect_to_user_feedback
|
||||
return
|
||||
elsif rfc = RequestForComment.unsolved.where(exercise_id: @submission.exercise, user_id: current_user.id).first
|
||||
# set a message that informs the user that his own RFC should be closed.
|
||||
flash[:notice] = I18n.t('exercises.submit.full_score_redirect_to_own_rfc')
|
||||
flash.keep(:notice)
|
||||
@ -405,8 +409,25 @@ class ExercisesController < ApplicationController
|
||||
return
|
||||
end
|
||||
end
|
||||
else
|
||||
# redirect to feedback page if score is less than 100 percent
|
||||
redirect_to_user_feedback
|
||||
return
|
||||
end
|
||||
redirect_to_lti_return_path
|
||||
end
|
||||
|
||||
def redirect_to_user_feedback
|
||||
url = if UserExerciseFeedback.find_by(exercise: @exercise, user: current_user)
|
||||
edit_user_exercise_feedback_path(user_exercise_feedback: {exercise_id: @exercise.id})
|
||||
else
|
||||
new_user_exercise_feedback_path(user_exercise_feedback: {exercise_id: @exercise.id})
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to(url) }
|
||||
format.json { render(json: {redirect: url}) }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
115
app/controllers/user_exercise_feedbacks_controller.rb
Normal file
115
app/controllers/user_exercise_feedbacks_controller.rb
Normal file
@ -0,0 +1,115 @@
|
||||
class UserExerciseFeedbacksController < ApplicationController
|
||||
include CommonBehavior
|
||||
|
||||
before_action :set_user_exercise_feedback, only: [:edit, :update]
|
||||
|
||||
def comment_presets
|
||||
[[0,t('user_exercise_feedback.difficulty_easy')],
|
||||
[1,t('user_exercise_feedback.difficulty_some_what_easy')],
|
||||
[2,t('user_exercise_feedback.difficulty_ok')],
|
||||
[3,t('user_exercise_feedback.difficulty_some_what_difficult')],
|
||||
[4,t('user_exercise_feedback.difficult_too_difficult')]]
|
||||
end
|
||||
|
||||
def time_presets
|
||||
[[0,t('user_exercise_feedback.estimated_time_less_5')],
|
||||
[1,t('user_exercise_feedback.estimated_time_5_to_10')],
|
||||
[2,t('user_exercise_feedback.estimated_time_10_to_20')],
|
||||
[3,t('user_exercise_feedback.estimated_time_20_to_30')],
|
||||
[4,t('user_exercise_feedback.estimated_time_more_30')]]
|
||||
end
|
||||
|
||||
def authorize!
|
||||
authorize(@uef)
|
||||
end
|
||||
private :authorize!
|
||||
|
||||
def create
|
||||
@exercise = Exercise.find(uef_params[:exercise_id])
|
||||
rfc = RequestForComment.unsolved.where(exercise_id: @exercise.id, user_id: current_user.id).first
|
||||
submission = current_user.submissions.where(exercise_id: @exercise.id).order('created_at DESC').first rescue nil
|
||||
|
||||
if @exercise
|
||||
@uef = UserExerciseFeedback.new(uef_params)
|
||||
if validate_inputs(uef_params)
|
||||
authorize!
|
||||
path =
|
||||
if rfc && submission && submission.normalized_score == 1.0
|
||||
request_for_comment_path(rfc)
|
||||
else
|
||||
implement_exercise_path(@exercise)
|
||||
end
|
||||
create_and_respond(object: @uef, path: proc{path})
|
||||
else
|
||||
flash[:danger] = t('shared.message_failure')
|
||||
redirect_to(:back, id: uef_params[:exercise_id])
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def destroy
|
||||
destroy_and_respond(object: @tag)
|
||||
end
|
||||
|
||||
def edit
|
||||
@texts = comment_presets.to_a
|
||||
@times = time_presets.to_a
|
||||
authorize!
|
||||
end
|
||||
|
||||
def uef_params
|
||||
params[:user_exercise_feedback].permit(:feedback_text, :difficulty, :exercise_id, :user_estimated_worktime).merge(user_id: current_user.id, user_type: current_user.class.name)
|
||||
end
|
||||
private :uef_params
|
||||
|
||||
def new
|
||||
@texts = comment_presets.to_a
|
||||
@times = time_presets.to_a
|
||||
@uef = UserExerciseFeedback.new
|
||||
@exercise = Exercise.find(params[:user_exercise_feedback][:exercise_id])
|
||||
authorize!
|
||||
end
|
||||
|
||||
def update
|
||||
submission = current_user.submissions.where(exercise_id: @exercise.id).order('created_at DESC').first rescue nil
|
||||
rfc = RequestForComment.unsolved.where(exercise_id: @exercise.id, user_id: current_user.id).first
|
||||
authorize!
|
||||
if @exercise && validate_inputs(uef_params)
|
||||
path =
|
||||
if rfc && submission && submission.normalized_score == 1.0
|
||||
request_for_comment_path(rfc)
|
||||
else
|
||||
implement_exercise_path(@exercise)
|
||||
end
|
||||
update_and_respond(object: @uef, params: uef_params, path: path)
|
||||
else
|
||||
flash[:danger] = t('shared.message_failure')
|
||||
redirect_to(:back, id: uef_params[:exercise_id])
|
||||
end
|
||||
end
|
||||
|
||||
def to_s
|
||||
name
|
||||
end
|
||||
|
||||
def set_user_exercise_feedback
|
||||
@exercise = Exercise.find(params[:user_exercise_feedback][:exercise_id])
|
||||
@uef = UserExerciseFeedback.find_by(exercise_id: params[:user_exercise_feedback][:exercise_id], user: current_user)
|
||||
end
|
||||
|
||||
def validate_inputs(uef_params)
|
||||
begin
|
||||
if uef_params[:difficulty].to_i < 0 || uef_params[:difficulty].to_i >= comment_presets.size
|
||||
return false
|
||||
elsif uef_params[:user_estimated_worktime].to_i < 0 || uef_params[:user_estimated_worktime].to_i >= time_presets.size
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
rescue
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
end
|
@ -1,8 +1,11 @@
|
||||
class UserExerciseFeedback < ActiveRecord::Base
|
||||
include Creation
|
||||
|
||||
belongs_to :user, polymorphic: true
|
||||
belongs_to :exercise
|
||||
|
||||
validates :user_id, uniqueness: { scope: [:exercise_id, :user_type] }
|
||||
|
||||
def to_s
|
||||
"User Exercise Feedback"
|
||||
end
|
||||
end
|
19
app/policies/user_exercise_feedback_policy.rb
Normal file
19
app/policies/user_exercise_feedback_policy.rb
Normal file
@ -0,0 +1,19 @@
|
||||
class UserExerciseFeedbackPolicy < ApplicationPolicy
|
||||
def author?
|
||||
@user == @record.author
|
||||
end
|
||||
private :author?
|
||||
|
||||
def create?
|
||||
everyone
|
||||
end
|
||||
|
||||
def new?
|
||||
everyone
|
||||
end
|
||||
|
||||
[:show? ,:destroy?, :edit?, :update?].each do |action|
|
||||
define_method(action) { admin? || author?}
|
||||
end
|
||||
|
||||
end
|
@ -1,5 +0,0 @@
|
||||
h5 =t('exercises.implement.comment.addComment')
|
||||
textarea#commentOnExercise.form-control(style='resize:none;')
|
||||
|
||||
p=''
|
||||
button#addCommentExerciseButton.btn.btn-block.btn-primary(type='button') =t('exercises.implement.comment.addCommentButton')
|
@ -20,7 +20,6 @@
|
||||
<u><%= t('activerecord.attributes.request_for_comments.question')%>:</u> <%= t('request_for_comments.no_question') %>
|
||||
<% end %>
|
||||
</h5>
|
||||
<button class="btn btn-warning" id="comment-exercise-button"><%= t('request_for_comments.comment_exercise') %></button>
|
||||
|
||||
<% if (policy(@request_for_comment).mark_as_solved? and not @request_for_comment.solved?) %>
|
||||
<button class="btn btn-primary" id="mark-as-solved-button"><%= t('request_for_comments.mark_as_solved') %></button>
|
||||
@ -62,7 +61,6 @@ also, all settings from the rails model needed for the editor configuration in t
|
||||
<% end %>
|
||||
|
||||
<%= render('shared/modal', id: 'comment-modal', title: t('exercises.implement.comment.dialogtitle'), template: 'exercises/_comment_dialogcontent') %>
|
||||
<%= render('shared/modal', id: 'comment-exercise-modal', title: t('exercises.implement.comment.addCommentExercise'), template: 'exercises/_comment_exercise_dialogcontent') %>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
@ -84,29 +82,6 @@ also, all settings from the rails model needed for the editor configuration in t
|
||||
});
|
||||
});
|
||||
|
||||
// comment exercise
|
||||
commentOnExerciseButton.on('click', function(){
|
||||
$('#comment-exercise-modal').modal('show');
|
||||
})
|
||||
|
||||
addCommentExerciseButton.on('click', function(event){
|
||||
var comment = $('#commentOnExercise').val();
|
||||
var url = $('#exercise_caption').data('comment-exercise-url');
|
||||
var jqrequest = $.ajax({
|
||||
dataType: 'json',
|
||||
method: 'POST',
|
||||
url: url,
|
||||
data: {
|
||||
exercise_id: $('#exercise_caption').data('exercise-id'),
|
||||
feedback_text: comment
|
||||
},
|
||||
dataType: 'json'
|
||||
});
|
||||
$('#comment-exercise-modal').modal('hide');
|
||||
});
|
||||
|
||||
|
||||
|
||||
// set file paths for ace
|
||||
var ACE_FILES_PATH = '/assets/ace/';
|
||||
_.each(['modePath', 'themePath', 'workerPath'], function(attribute) {
|
||||
|
23
app/views/user_exercise_feedbacks/_form.html.slim
Normal file
23
app/views/user_exercise_feedbacks/_form.html.slim
Normal file
@ -0,0 +1,23 @@
|
||||
= form_for(@uef) do |f|
|
||||
div
|
||||
span.badge.pull-right.score
|
||||
|
||||
h1 id="exercise-headline"
|
||||
= t('activerecord.models.user_exercise_feedback.one') + " "
|
||||
= link_to(@exercise.title, [:implement, @exercise])
|
||||
= render('shared/form_errors', object: @uef)
|
||||
h4
|
||||
== t('user_exercise_feedback.description')
|
||||
#description-panel.lead.description-panel
|
||||
u = t('activerecord.attributes.exercise.description')
|
||||
= render_markdown(@exercise.description)
|
||||
.form-group
|
||||
= f.text_area(:feedback_text, class: 'form-control', required: true, :rows => "10")
|
||||
h4 = t('user_exercise_feedback.difficulty')
|
||||
= f.collection_radio_buttons :difficulty, @texts, :first, :last, html_options={class: "radio-inline"} do |b|
|
||||
= b.label(:class => 'radio') { b.radio_button + b.text }
|
||||
h4 = t('user_exercise_feedback.working_time')
|
||||
= f.collection_radio_buttons :user_estimated_worktime, @times, :first, :last, html_options={class: "radio-inline"} do |b|
|
||||
= b.label(:class => 'radio') { b.radio_button + b.text }
|
||||
= f.hidden_field(:exercise_id, :value => @exercise.id)
|
||||
.actions = render('shared/submit_button', f: f, object: @uef)
|
1
app/views/user_exercise_feedbacks/edit.html.slim
Normal file
1
app/views/user_exercise_feedbacks/edit.html.slim
Normal file
@ -0,0 +1 @@
|
||||
= render('form')
|
1
app/views/user_exercise_feedbacks/new.html.slim
Normal file
1
app/views/user_exercise_feedbacks/new.html.slim
Normal file
@ -0,0 +1 @@
|
||||
= render('form')
|
@ -152,6 +152,9 @@ de:
|
||||
submission:
|
||||
one: Abgabe
|
||||
other: Abgaben
|
||||
user_exercise_feedback:
|
||||
one: Feedback
|
||||
other: Feedback
|
||||
errors:
|
||||
messages:
|
||||
together: 'muss zusammen mit %{attribute} definiert werden'
|
||||
@ -525,3 +528,18 @@ de:
|
||||
previous_label: '← Vorherige Seite'
|
||||
file_template:
|
||||
no_template_label: "Leere Datei"
|
||||
user_exercise_feedback:
|
||||
difficulty_easy: "Die Aufgabe war zu einfach"
|
||||
difficulty_some_what_easy: "Die Aufgabe war etwas zu einfach"
|
||||
difficulty_ok: "Die Aufgabe war gut zu lösen"
|
||||
difficulty_some_what_difficult: "Die Aufgabe war etwas zu schwer"
|
||||
difficult_too_difficult: "Die Aufgabe war zu schwer"
|
||||
difficulty: "Schwierigkeit der Aufgabe:"
|
||||
description: "Ihre Punkte wurden übertragen. Wir würden uns freuen, wenn Sie uns hier Feedback zur Aufgabe geben.<br> Wenn sie das nicht möchten, können Sie das Fenster auch einfach schließen.<br><br>Bitte beschreiben Sie, was Ihnen an der Aufgabe gefallen hat und was nicht. Gab es Schwierigkeiten bei der Aufgabe? War die Aufgabe zu leicht oder zu schwer?<br>Wir freuen uns über jedes Feedback."
|
||||
estimated_time_less_5: "weniger als 5 Minuten"
|
||||
estimated_time_5_to_10: "zwischen 5 und 10 Minuten"
|
||||
estimated_time_10_to_20: "zwischen 10 und 20 Minuten"
|
||||
estimated_time_20_to_30: "zwischen 20 und 30 Minuten"
|
||||
estimated_time_more_30: "mehr als 30 Minuten"
|
||||
working_time: "Geschätze Bearbeitungszeit für diese Aufgabe:"
|
||||
|
||||
|
@ -173,6 +173,9 @@ en:
|
||||
submission:
|
||||
one: Submission
|
||||
other: Submissions
|
||||
user_exercise_feedback:
|
||||
one: Feedback
|
||||
other: Feedback
|
||||
errors:
|
||||
messages:
|
||||
together: 'has to be set along with %{attribute}'
|
||||
@ -546,4 +549,17 @@ en:
|
||||
previous_label: '← Previous Page'
|
||||
file_template:
|
||||
no_template_label: "Empty File"
|
||||
|
||||
user_exercise_feedback:
|
||||
difficulty_easy: "the exercise was too easy"
|
||||
difficulty_some_what_easy: "the exercise was somewhat easy"
|
||||
difficulty_ok: "the difficulty of the exercise was just right"
|
||||
difficulty_some_what_difficult: "the exercise was somewhat difficult"
|
||||
difficult_too_difficult: "the exercise was too difficult"
|
||||
difficulty: "Difficulty of the exercise:"
|
||||
description: "Your points have been submitted. We kindly ask you for feedback for this exercise. <br> If you do not want to give feedback you can simply close this window.<br><br>Please describe what you liked on this exercise and what you did not. Was the exercise easy to understand or did you have problems understanding? How was the difficulty of the exercise to you?<br>We are happy about any feedback."
|
||||
estimated_time_less_5: "less than 5 minutes"
|
||||
estimated_time_5_to_10: "between 5 and 10 minutes"
|
||||
estimated_time_10_to_20: "between 10 and 20 minutes"
|
||||
estimated_time_20_to_30: "between 20 and 30 minutes"
|
||||
estimated_time_more_30: "more than 30 minutes"
|
||||
working_time: "Estimated time working on this exercise:"
|
||||
|
@ -86,6 +86,13 @@ Rails.application.routes.draw do
|
||||
end
|
||||
end
|
||||
|
||||
resources :user_exercise_feedbacks do
|
||||
member do
|
||||
get :reload
|
||||
post :submit
|
||||
end
|
||||
end
|
||||
|
||||
resources :interventions do
|
||||
member do
|
||||
post :clone
|
||||
|
5
db/migrate/20170411090543_improve_user_feedback.rb
Normal file
5
db/migrate/20170411090543_improve_user_feedback.rb
Normal file
@ -0,0 +1,5 @@
|
||||
class ImproveUserFeedback < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :user_exercise_feedbacks, :user_estimated_worktime, :integer
|
||||
end
|
||||
end
|
Reference in New Issue
Block a user