From d343e74287cb8dd4f67054a119a326773201b6b7 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Thu, 28 Jan 2016 17:52:34 +0100 Subject: [PATCH 1/7] Add sorting to external user statistics table --- app/views/external_users/statistics.html.slim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/external_users/statistics.html.slim b/app/views/external_users/statistics.html.slim index a8873cb3..a1f78f73 100644 --- a/app/views/external_users/statistics.html.slim +++ b/app/views/external_users/statistics.html.slim @@ -3,7 +3,7 @@ h1 = t('.title') - exercises = Exercise.where(:id => @user.submissions.group(:exercise_id).select(:exercise_id).distinct()) .table-responsive - table.table + table.table.table-striped.sortable thead tr - ['.exercise', '.score', '.runs', '.worktime'].each do |title| From 4ebaee893186746700d2438dffd35c238808ac43 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Thu, 4 Feb 2016 11:36:00 +0100 Subject: [PATCH 2/7] Add working time delta for each submission --- app/views/exercises/external_users/statistics.html.slim | 7 +++++-- config/locales/de.yml | 2 ++ config/locales/en.yml | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/views/exercises/external_users/statistics.html.slim b/app/views/exercises/external_users/statistics.html.slim index 79f6458d..2bd640c1 100644 --- a/app/views/exercises/external_users/statistics.html.slim +++ b/app/views/exercises/external_users/statistics.html.slim @@ -38,14 +38,17 @@ h1 = "#{@exercise} (external user #{@external_user})" table.table thead tr - - ['.time', '.cause', '.score'].each do |title| + - ['.time', '.cause', '.score', '.time_difference'].each do |title| th.header = t(title) tbody - - submissions.each do |submission| + - deltas = submissions.map.with_index {|item, index| delta = item.created_at - submissions[index - 1].created_at if index > 0; if delta == nil or delta > 30*60 then 0 else delta end} + - submissions.each_with_index do |submission, index| tr data-id=submission.id td.clickable = submission.created_at.strftime("%F %T") td = submission.cause td = submission.score + td = Time.at(deltas[1..index].inject(:+)).utc.strftime("%H:%M:%S") if index > 0 + p = t('.addendum') - else p = t('.no_data_available') diff --git a/config/locales/de.yml b/config/locales/de.yml index 9fd2dce0..91898861 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -264,6 +264,8 @@ de: time: Zeit cause: Grund score: Punktzahl + time_difference: 'Arbeitszeit bis hier*' + addendum: '* Differenzen von mehr als 30 Minuten werden ignoriert.' external_users: statistics: title: Statistiken für Externe Benutzer diff --git a/config/locales/en.yml b/config/locales/en.yml index f005eea2..a4e7b616 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -264,6 +264,8 @@ en: time: Time cause: Cause score: Score + time_difference: 'Working Time until here*' + addendum: '* Deltas longer than 30 minutes are ignored.' external_users: statistics: title: External User Statistics From 0a5301a595f19414dccc5d9858f920f9062aae44 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Wed, 24 Feb 2016 14:23:15 +0100 Subject: [PATCH 3/7] Make statistics teacher-safe --- app/models/internal_user.rb | 4 ++++ app/policies/external_user_policy.rb | 2 +- app/views/exercises/statistics.html.slim | 3 ++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/models/internal_user.rb b/app/models/internal_user.rb index 26227522..54b8df4d 100644 --- a/app/models/internal_user.rb +++ b/app/models/internal_user.rb @@ -17,4 +17,8 @@ class InternalUser < ActiveRecord::Base activation_token? || reset_password_token? end private :password_void? + + def teacher? + role == 'teacher' + end end diff --git a/app/policies/external_user_policy.rb b/app/policies/external_user_policy.rb index 5932e3f0..2e11060b 100644 --- a/app/policies/external_user_policy.rb +++ b/app/policies/external_user_policy.rb @@ -1,5 +1,5 @@ class ExternalUserPolicy < AdminOnlyPolicy def statistics? - admin? || author? || team_member? + admin? end end diff --git a/app/views/exercises/statistics.html.slim b/app/views/exercises/statistics.html.slim index c4df3e16..717535be 100644 --- a/app/views/exercises/statistics.html.slim +++ b/app/views/exercises/statistics.html.slim @@ -22,8 +22,9 @@ h1 = @exercise tbody - @exercise.send(symbol).distinct().each do |user| - if user_statistics[user.id] then us = user_statistics[user.id] else us = {"maximum_score" => nil, "runs" => nil} + - label = current_user.teacher? ? "#{user.name}" : "#{user.name} (#{user.email})" tr - td = link_to_if symbol==:external_users, "#{user.name} (#{user.email})", {controller: "exercises", action: "statistics", external_user_id: user.id, id: @exercise.id} + td = link_to_if symbol==:external_users, label, {controller: "exercises", action: "statistics", external_user_id: user.id, id: @exercise.id} td = us['maximum_score'] or 0 td = us['runs'] td = @exercise.average_working_time_for(user.id) or 0 From da3339ecbbeb9b624294a39a037452a49928eaa6 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Wed, 2 Mar 2016 10:57:13 +0100 Subject: [PATCH 4/7] Hide file types, execution environments, and teams from teachers --- app/policies/execution_environment_policy.rb | 2 +- app/policies/file_type_policy.rb | 2 +- app/policies/team_policy.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/policies/execution_environment_policy.rb b/app/policies/execution_environment_policy.rb index bccc9a07..51eabdf3 100644 --- a/app/policies/execution_environment_policy.rb +++ b/app/policies/execution_environment_policy.rb @@ -1,4 +1,4 @@ -class ExecutionEnvironmentPolicy < AdminOrAuthorPolicy +class ExecutionEnvironmentPolicy < AdminOnlyPolicy def author? @user == @record.author end diff --git a/app/policies/file_type_policy.rb b/app/policies/file_type_policy.rb index a5cbfe3d..aa566b12 100644 --- a/app/policies/file_type_policy.rb +++ b/app/policies/file_type_policy.rb @@ -1,4 +1,4 @@ -class FileTypePolicy < AdminOrAuthorPolicy +class FileTypePolicy < AdminOnlyPolicy def author? @user == @record.author end diff --git a/app/policies/team_policy.rb b/app/policies/team_policy.rb index ed48699d..ff05c0c3 100644 --- a/app/policies/team_policy.rb +++ b/app/policies/team_policy.rb @@ -1,6 +1,6 @@ class TeamPolicy < ApplicationPolicy [:create?, :index?, :new?].each do |action| - define_method(action) { @user.internal_user? } + define_method(action) { admin? } end [:destroy?, :edit?, :show?, :update?].each do |action| From 7dee100665a9fa2fbeb1ea77b0fa483710d494a6 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Wed, 2 Mar 2016 11:55:26 +0100 Subject: [PATCH 5/7] Hide actions that are not available to teachers --- app/policies/exercise_policy.rb | 6 +++++- app/views/exercises/index.html.slim | 18 +++++++++--------- app/views/exercises/show.html.slim | 10 ++++++---- app/views/shared/_file.html.slim | 2 +- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/app/policies/exercise_policy.rb b/app/policies/exercise_policy.rb index 1e4cf150..29a1c570 100644 --- a/app/policies/exercise_policy.rb +++ b/app/policies/exercise_policy.rb @@ -8,7 +8,11 @@ class ExercisePolicy < AdminOrAuthorPolicy admin? end - [:clone?, :destroy?, :edit?, :show?, :statistics?, :update?].each do |action| + def show? + @user.internal_user? + end + + [:clone?, :destroy?, :edit?, :statistics?, :update?].each do |action| define_method(action) { admin? || author? || team_member? } end diff --git a/app/views/exercises/index.html.slim b/app/views/exercises/index.html.slim index d6e37ca9..47714943 100644 --- a/app/views/exercises/index.html.slim +++ b/app/views/exercises/index.html.slim @@ -27,17 +27,17 @@ h1 = Exercise.model_name.human(count: 2) - @exercises.each do |exercise| tr data-id=exercise.id td = exercise.title - td = link_to(exercise.author, exercise.author) - td = link_to(exercise.execution_environment, exercise.execution_environment) + td = link_to_if(policy(exercise.author).show?, exercise.author, exercise.author) + td = link_to_if(policy(exercise.execution_environment).show?, exercise.execution_environment, exercise.execution_environment) td = exercise.files.teacher_defined_tests.count td = exercise.maximum_score td.public data-value=exercise.public? = symbol_for(exercise.public?) - td = link_to(t('shared.show'), exercise) - td = link_to(t('shared.edit'), edit_exercise_path(exercise)) - td = link_to(t('shared.destroy'), exercise, data: {confirm: t('shared.confirm_destroy')}, method: :delete) - td = link_to(t('.clone'), clone_exercise_path(exercise), data: {confirm: t('shared.confirm_destroy')}, method: :post) - td = link_to(t('.implement'), implement_exercise_path(exercise)) - td = link_to(t('shared.statistics'), statistics_exercise_path(exercise)) + td = link_to(t('shared.show'), exercise) if policy(exercise).show? + td = link_to(t('shared.edit'), edit_exercise_path(exercise)) if policy(exercise).edit? + td = link_to(t('shared.destroy'), exercise, data: {confirm: t('shared.confirm_destroy')}, method: :delete) if policy(exercise).destroy? + td = link_to(t('.clone'), clone_exercise_path(exercise), data: {confirm: t('shared.confirm_destroy')}, method: :post) if policy(exercise).clone? + td = link_to(t('.implement'), implement_exercise_path(exercise)) if policy(exercise).implement? + td = link_to(t('shared.statistics'), statistics_exercise_path(exercise)) if policy(exercise).statistics? = render('shared/pagination', collection: @exercises) -p = render('shared/new_button', model: Exercise) \ No newline at end of file +p = render('shared/new_button', model: Exercise) diff --git a/app/views/exercises/show.html.slim b/app/views/exercises/show.html.slim index 67185046..dbeca3d3 100644 --- a/app/views/exercises/show.html.slim +++ b/app/views/exercises/show.html.slim @@ -4,12 +4,13 @@ h1 = @exercise - = render('shared/edit_button', object: @exercise) + - if policy(@exercise).edit? + = render('shared/edit_button', object: @exercise) = row(label: 'exercise.title', value: @exercise.title) -= row(label: 'exercise.user', value: link_to(@exercise.author, @exercise.author)) += row(label: 'exercise.user', value: link_to_if(policy(@exercise.author).show?, @exercise.author, @exercise.author)) = row(label: 'exercise.description', value: @exercise.description) -= row(label: 'exercise.execution_environment', value: link_to(@exercise.execution_environment, @exercise.execution_environment)) += row(label: 'exercise.execution_environment', value: link_to_if(policy(@exercise.execution_environment).show?, @exercise.execution_environment, @exercise.execution_environment)) = row(label: 'exercise.instructions', value: render_markdown(@exercise.instructions)) = row(label: 'exercise.team', value: @exercise.team ? link_to(@exercise.team, @exercise.team) : nil) = row(label: 'exercise.maximum_score', value: @exercise.maximum_score) @@ -26,5 +27,6 @@ ul.list-unstyled .panel-heading h3.panel-title = file.name_with_extension .panel-body - .clearfix = link_to(t('shared.destroy'), file, class:'btn btn-warning btn-sm pull-right', data: {confirm: t('shared.confirm_destroy')}, method: :delete) + - 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) = render('shared/file', file: file) diff --git a/app/views/shared/_file.html.slim b/app/views/shared/_file.html.slim index f1f7a905..1e50388c 100644 --- a/app/views/shared/_file.html.slim +++ b/app/views/shared/_file.html.slim @@ -1,6 +1,6 @@ = row(label: 'file.name', value: file.name) = row(label: 'file.path', value: file.path) -= row(label: 'file.file_type', value: link_to(file.file_type, file.file_type)) += row(label: 'file.file_type', value: link_to_if(policy(file).show?, file.file_type, file.file_type)) = row(label: 'file.role', value: file.role? ? t("files.roles.#{file.role}") : '') = row(label: 'file.hidden', value: file.hidden) = row(label: 'file.read_only', value: file.read_only) From 551552279bd2a1a8036c90bbe4e1c77f7eef1b39 Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Wed, 2 Mar 2016 12:17:20 +0100 Subject: [PATCH 6/7] Update schema.rb --- db/schema.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/db/schema.rb b/db/schema.rb index 793c021a..1ec47e98 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -91,6 +91,8 @@ ActiveRecord::Schema.define(version: 20160204111716) do t.boolean "hide_file_tree" 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" @@ -200,6 +202,9 @@ ActiveRecord::Schema.define(version: 20160204111716) do 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" From b66e9fc05d4d8eb49d6eb478aa19fa692d1fb20f Mon Sep 17 00:00:00 2001 From: Maximilian Grundke Date: Wed, 2 Mar 2016 14:52:39 +0100 Subject: [PATCH 7/7] Add Testrun to schema --- app/models/testrun.rb | 4 ++++ db/migrate/20160302133540_create_testruns.rb | 13 +++++++++++++ db/schema.rb | 11 ++++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 app/models/testrun.rb create mode 100644 db/migrate/20160302133540_create_testruns.rb diff --git a/app/models/testrun.rb b/app/models/testrun.rb new file mode 100644 index 00000000..316acfdc --- /dev/null +++ b/app/models/testrun.rb @@ -0,0 +1,4 @@ +class Testrun < ActiveRecord::Base + belongs_to :file + belongs_to :submission +end diff --git a/db/migrate/20160302133540_create_testruns.rb b/db/migrate/20160302133540_create_testruns.rb new file mode 100644 index 00000000..7590f2a3 --- /dev/null +++ b/db/migrate/20160302133540_create_testruns.rb @@ -0,0 +1,13 @@ +class CreateTestruns < ActiveRecord::Migration + def change + create_table :testruns do |t| + t.boolean :passed + t.text :output + + t.belongs_to :file + t.belongs_to :submission + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 1ec47e98..4ba78542 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: 20160204111716) do +ActiveRecord::Schema.define(version: 20160302133540) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -211,4 +211,13 @@ ActiveRecord::Schema.define(version: 20160204111716) do 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