diff --git a/app/assets/stylesheets/exercises.css.scss b/app/assets/stylesheets/exercises.css.scss index 73c0b26e..e46d59af 100644 --- a/app/assets/stylesheets/exercises.css.scss +++ b/app/assets/stylesheets/exercises.css.scss @@ -93,4 +93,16 @@ a.file-heading { margin: -1px 0 0 0; top: 100%; left: 0; -} \ No newline at end of file +} + +.feedback { + .text { + margin-bottom: 10px; + } + .difficulty { + font-weight: bold; + } + .worktime { + font-weight: bold; + } +} diff --git a/app/controllers/exercises_controller.rb b/app/controllers/exercises_controller.rb index 141b47ee..969e5e4f 100644 --- a/app/controllers/exercises_controller.rb +++ b/app/controllers/exercises_controller.rb @@ -6,7 +6,7 @@ class ExercisesController < ApplicationController before_action :handle_file_uploads, only: [:create, :update] before_action :set_execution_environments, only: [:create, :edit, :new, :update] - before_action :set_exercise, only: MEMBER_ACTIONS + [:clone, :implement, :working_times, :intervention, :search, :run, :statistics, :submit, :reload] + before_action :set_exercise, only: MEMBER_ACTIONS + [:clone, :implement, :working_times, :intervention, :search, :run, :statistics, :submit, :reload, :feedback] before_action :set_external_user, only: [:statistics] before_action :set_file_types, only: [:create, :edit, :new, :update] before_action :set_course_token, only: [:implement] @@ -90,6 +90,11 @@ class ExercisesController < ApplicationController collect_set_and_unset_exercise_tags end + def feedback + authorize! + @feedbacks = @exercise.user_exercise_feedbacks.paginate(page: params[:page]) + end + def import_proforma_xml begin user = user_for_oauth2_request() diff --git a/app/models/exercise.rb b/app/models/exercise.rb index 58d328ae..b7487399 100644 --- a/app/models/exercise.rb +++ b/app/models/exercise.rb @@ -20,6 +20,7 @@ class Exercise < ActiveRecord::Base has_many :exercise_tags has_many :tags, through: :exercise_tags accepts_nested_attributes_for :exercise_tags + has_many :user_exercise_feedbacks has_many :external_users, source: :user, source_type: ExternalUser, through: :submissions has_many :internal_users, source: :user, source_type: InternalUser, through: :submissions diff --git a/app/policies/exercise_policy.rb b/app/policies/exercise_policy.rb index 54d22b87..e4563832 100644 --- a/app/policies/exercise_policy.rb +++ b/app/policies/exercise_policy.rb @@ -12,7 +12,7 @@ class ExercisePolicy < AdminOrAuthorPolicy @user.internal_user? end - [:clone?, :destroy?, :edit?, :statistics?, :update?].each do |action| + [:clone?, :destroy?, :edit?, :statistics?, :update?, :feedback?].each do |action| define_method(action) { admin? || author?} end diff --git a/app/views/exercises/feedback.html.slim b/app/views/exercises/feedback.html.slim new file mode 100644 index 00000000..07b88167 --- /dev/null +++ b/app/views/exercises/feedback.html.slim @@ -0,0 +1,15 @@ +h1 = @exercise + +ul.list-unstyled.panel-group#files + - @feedbacks.each do |feedback| + li.panel.panel-default + .panel-heading role="tab" id="heading" + div.clearfix + span = feedback.user.name + .panel-collapse role="tabpanel" + .panel-body.feedback + .text = feedback.feedback_text + .difficulty = "#{t('user_exercise_feedback.difficulty')} #{feedback.difficulty}" if feedback.difficulty + .worktime = "#{t('user_exercise_feedback.working_time')} #{feedback.user_estimated_worktime}" if feedback.user_estimated_worktime + += render('shared/pagination', collection: @feedbacks) diff --git a/app/views/exercises/index.html.slim b/app/views/exercises/index.html.slim index bd8fe880..18c2cd98 100644 --- a/app/views/exercises/index.html.slim +++ b/app/views/exercises/index.html.slim @@ -47,6 +47,7 @@ h1 = Exercise.model_name.human(count: 2) span.sr-only Toggle Dropdown ul.dropdown-menu.pull-right role="menu" li = link_to(t('shared.show'), exercise) if policy(exercise).show? + li = link_to(t('activerecord.models.user_exercise_feedback.other'), feedback_exercise_path(exercise)) if policy(exercise).feedback? li = link_to(t('shared.destroy'), exercise, data: {confirm: t('shared.confirm_destroy')}, method: :delete) if policy(exercise).destroy? li = link_to(t('.clone'), clone_exercise_path(exercise), data: {confirm: t('shared.confirm_destroy')}, method: :post) if policy(exercise).clone? diff --git a/config/locales/de.yml b/config/locales/de.yml index afeea353..a7a2b436 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -328,6 +328,7 @@ de: clone: Duplizieren implement: Implementieren test_files: Test-Dateien + feedback: Feedback statistics: average_score: Durchschnittliche Punktzahl final_submissions: Finale Abgaben diff --git a/config/locales/en.yml b/config/locales/en.yml index 6c1d91fd..7eba1527 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -328,6 +328,7 @@ en: clone: Duplicate implement: Implement test_files: Test Files + feedback: Feedback statistics: average_score: Average Score final_submissions: Final Submissions diff --git a/config/routes.rb b/config/routes.rb index b6fef404..264e7471 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -76,6 +76,7 @@ Rails.application.routes.draw do post :intervention post :search get :statistics + get :feedback get :reload post :submit end