- <% if current_user.can_view_users?(lecture) %>
+ <% if current_user.can_update_personell?(lecture) %>
<%= link_to t('admin.tutorial.new'),
From 4abf4bd0cbf6cc6a3e65188d5c639f6900720573 Mon Sep 17 00:00:00 2001
From: fosterfarrell9 <28628554+fosterfarrell9@users.noreply.github.com>
Date: Sun, 7 May 2023 11:16:47 +0200
Subject: [PATCH 10/22] fix broken create lecture action
---
app/controllers/lectures_controller.rb | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/app/controllers/lectures_controller.rb b/app/controllers/lectures_controller.rb
index b9d0f4a80..3ef5b2d08 100644
--- a/app/controllers/lectures_controller.rb
+++ b/app/controllers/lectures_controller.rb
@@ -306,9 +306,12 @@ def lecture_params
:disable_teacher_display, :content_mode, :passphrase,
:sort, :comments_disabled, :submission_max_team_size,
:submission_grace_period]
- if current_user.can_update_personell?(@lecture)
+ if action_name == 'update' && current_user.can_update_personell?(@lecture)
allowed_params.concat([:teacher_id, editor_ids: []])
end
+ if action_name == 'create'
+ allowed_params.concat([:course_id, :teacher_id, editor_ids: []])
+ end
params.require(:lecture).permit(allowed_params)
end
From d00d5af03b3f76a641ecf2c71c24f2564844506e Mon Sep 17 00:00:00 2001
From: Splines <37160523+Splines@users.noreply.github.com>
Date: Thu, 11 May 2023 17:04:49 +0200
Subject: [PATCH 11/22] Update rubocop version (#494)
* Update rubocop version
The old version does not work with the Ruby LSP VS Code extension.
* Exclude some rubocop metrics (for now)
* Reflect rubocop version update in lockfile
---
.rubocop.yml | 19 ++++++++++++++++++-
Gemfile | 2 +-
Gemfile.lock | 22 ++++++++++++----------
3 files changed, 31 insertions(+), 12 deletions(-)
diff --git a/.rubocop.yml b/.rubocop.yml
index b3cc9d86d..d7b548944 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -201,6 +201,9 @@ Style/RedundantFreeze:
Style/SymbolProc:
Enabled: true
+Style/SymbolArray:
+ Enabled: false
+
# Use `foo {}` not `foo{}`.
Layout/SpaceBeforeBlockBraces:
Enabled: true
@@ -321,4 +324,18 @@ Performance/DeletePrefix:
Enabled: true
Performance/DeleteSuffix:
- Enabled: true
\ No newline at end of file
+ Enabled: true
+
+Metrics/ModuleLength:
+ Enabled: false
+
+Metrics/ClassLength:
+ Enabled: false
+
+Metrics/MethodLength:
+ Exclude:
+ - 'app/abilities/**/*'
+
+Metrics/AbcSize:
+ Exclude:
+ - 'app/abilities/**/*'
\ No newline at end of file
diff --git a/Gemfile b/Gemfile
index c97d4a8eb..d24e6e02c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -120,7 +120,7 @@ group :development, :docker_development do
# Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
gem "spring"
gem "spring-watcher-listen", "~> 2.0.0"
- gem "rubocop", "~> 0.93", require: false
+ gem "rubocop", "~> 1.50", require: false
gem "rubocop-packaging", require: false
gem "rubocop-performance", require: false
gem "rubocop-rails", require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index dd090e8af..5f8fb5465 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -304,6 +304,7 @@ GEM
js-routes (1.4.9)
railties (>= 4)
sprockets-rails
+ json (2.6.3)
jsonapi-renderer (0.2.2)
kaminari (1.2.2)
activesupport (>= 4.1.0)
@@ -377,7 +378,7 @@ GEM
options (2.3.2)
orm_adapter (0.5.0)
pairing_heap (3.0.0)
- parallel (1.22.1)
+ parallel (1.23.0)
parser (3.2.2.0)
ast (~> 2.4.1)
pdf-reader (2.11.0)
@@ -458,7 +459,7 @@ GEM
ffi (~> 1.0)
redis-client (0.14.1)
connection_pool
- regexp_parser (2.7.0)
+ regexp_parser (2.8.0)
request_store (1.5.1)
rack (>= 1.4)
responders (3.1.0)
@@ -499,15 +500,16 @@ GEM
rspec-mocks (~> 3.11)
rspec-support (~> 3.11)
rspec-support (3.12.0)
- rubocop (0.93.1)
+ rubocop (1.50.2)
+ json (~> 2.3)
parallel (~> 1.10)
- parser (>= 2.7.1.5)
+ parser (>= 3.2.0.0)
rainbow (>= 2.2.2, < 4.0)
- regexp_parser (>= 1.8)
- rexml
- rubocop-ast (>= 0.6.0)
+ regexp_parser (>= 1.8, < 3.0)
+ rexml (>= 3.2.5, < 4.0)
+ rubocop-ast (>= 1.28.0, < 2.0)
ruby-progressbar (~> 1.7)
- unicode-display_width (>= 1.4.0, < 2.0)
+ unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.28.0)
parser (>= 3.2.1.0)
rubocop-packaging (0.5.1)
@@ -629,7 +631,7 @@ GEM
unf (0.1.4)
unf_ext
unf_ext (0.0.8.2)
- unicode-display_width (1.8.0)
+ unicode-display_width (2.4.2)
warden (1.2.9)
rack (>= 2.0.9)
web-console (4.2.0)
@@ -718,7 +720,7 @@ DEPENDENCIES
rgl
rqrcode
rspec-rails
- rubocop (~> 0.93)
+ rubocop (~> 1.50)
rubocop-packaging
rubocop-performance
rubocop-rails
From 5f7c956e60994bca9f965511e491fadac788344e Mon Sep 17 00:00:00 2001
From: Splines <37160523+Splines@users.noreply.github.com>
Date: Thu, 11 May 2023 17:05:39 +0200
Subject: [PATCH 12/22] Enforce rubocop layout rules (#495)
* Update rubocop version
The old version does not work with the Ruby LSP VS Code extension.
* Exclude some rubocop metrics (for now)
* Enforce rubocop layout rules
---
app/abilities/administration_ability.rb | 2 +-
app/abilities/announcement_ability.rb | 4 +-
app/abilities/answer_ability.rb | 2 +-
app/abilities/assignment_ability.rb | 2 +-
app/abilities/chapter_ability.rb | 2 +-
app/abilities/course_ability.rb | 2 +-
app/abilities/division_ability.rb | 2 +-
app/abilities/erdbeere_ability.rb | 2 +-
app/abilities/interaction_ability.rb | 2 +-
app/abilities/item_ability.rb | 4 +-
app/abilities/lecture_ability.rb | 2 +-
app/abilities/lesson_ability.rb | 2 +-
app/abilities/main_ability.rb | 2 +-
app/abilities/medium_ability.rb | 8 +-
app/abilities/notification_ability.rb | 2 +-
app/abilities/profile_ability.rb | 2 +-
app/abilities/program_ability.rb | 2 +-
app/abilities/question_ability.rb | 2 +-
app/abilities/quiz_ability.rb | 2 +-
app/abilities/quiz_certificate_ability.rb | 2 +-
app/abilities/referral_ability.rb | 2 +-
app/abilities/remark_ability.rb | 2 +-
app/abilities/search_ability.rb | 2 +-
app/abilities/section_ability.rb | 2 +-
app/abilities/subject_ability.rb | 2 +-
app/abilities/submission_ability.rb | 6 +-
app/abilities/tag_ability.rb | 1 -
app/abilities/term_ability.rb | 2 +-
app/abilities/tutorial_ability.rb | 6 +-
app/abilities/watchlist_ability.rb | 2 +-
app/controllers/announcements_controller.rb | 79 ++--
app/controllers/answers_controller.rb | 19 +-
app/controllers/application_controller.rb | 110 ++---
app/controllers/assignments_controller.rb | 43 +-
app/controllers/chapters_controller.rb | 31 +-
app/controllers/clicker_votes_controller.rb | 6 +-
app/controllers/clickers_controller.rb | 31 +-
app/controllers/confirmations_controller.rb | 11 +-
app/controllers/courses_controller.rb | 113 ++---
app/controllers/divisions_controller.rb | 56 +--
app/controllers/erdbeere_controller.rb | 92 ++--
app/controllers/interactions_controller.rb | 32 +-
app/controllers/items_controller.rb | 39 +-
app/controllers/lectures_controller.rb | 272 +++++------
app/controllers/lessons_controller.rb | 45 +-
app/controllers/main_controller.rb | 16 +-
app/controllers/media_controller.rb | 441 +++++++++---------
app/controllers/notifications_controller.rb | 12 +-
app/controllers/profile_controller.rb | 160 ++++---
app/controllers/programs_controller.rb | 57 ++-
app/controllers/questions_controller.rb | 71 +--
.../quiz_certificates_controller.rb | 48 +-
app/controllers/quizzes_controller.rb | 105 +++--
app/controllers/readers_controller.rb | 9 +-
app/controllers/referrals_controller.rb | 69 +--
app/controllers/registrations_controller.rb | 41 +-
app/controllers/remarks_controller.rb | 25 +-
app/controllers/search_controller.rb | 42 +-
app/controllers/sections_controller.rb | 70 +--
app/controllers/sessions_controller.rb | 3 +-
app/controllers/subjects_controller.rb | 30 +-
app/controllers/submissions_controller.rb | 399 ++++++++--------
app/controllers/tags_controller.rb | 298 ++++++------
app/controllers/terms_controller.rb | 25 +-
app/controllers/tutorials_controller.rb | 131 +++---
app/controllers/users_controller.rb | 37 +-
app/controllers/vertices_controller.rb | 83 ++--
.../watchlist_entries_controller.rb | 1 -
app/controllers/watchlists_controller.rb | 8 +-
app/helpers/announcements_helper.rb | 2 +
app/helpers/application_helper.rb | 50 +-
app/helpers/assignments_helper.rb | 3 +
app/helpers/chapters_helper.rb | 2 +-
app/helpers/clickers_helper.rb | 2 +-
app/helpers/courses_helper.rb | 2 +-
app/helpers/items_helper.rb | 1 +
app/helpers/lectures_helper.rb | 18 +-
app/helpers/lessons_helper.rb | 1 +
app/helpers/media_helper.rb | 15 +-
app/helpers/notifications_helper.rb | 53 ++-
app/helpers/referrals_helper.rb | 7 +-
app/helpers/search_helper.rb | 4 +-
app/helpers/submissions_helper.rb | 62 ++-
app/helpers/talks_helper.rb | 5 +-
app/helpers/tutorials_helper.rb | 4 +-
app/helpers/vertices_helper.rb | 2 +-
app/mailers/application_mailer.rb | 4 +-
.../exception_handler/exception_mailer.rb | 3 +-
app/mailers/mathi_mailer.rb | 4 +-
app/mailers/my_mailer.rb | 4 +-
app/mailers/notification_mailer.rb | 55 ++-
app/models/ability.rb | 2 +-
app/models/announcement.rb | 2 +-
app/models/answer.rb | 33 +-
app/models/assignment.rb | 28 +-
app/models/chapter.rb | 5 +-
app/models/clicker.rb | 9 +-
app/models/clicker_vote.rb | 19 +-
app/models/course_self_join.rb | 8 +-
app/models/course_tag_join.rb | 9 +-
app/models/division.rb | 12 +-
app/models/interaction.rb | 12 +-
app/models/interactions_record.rb | 2 +-
app/models/item.rb | 328 +++++++------
app/models/item_self_join.rb | 57 +--
app/models/lecture.rb | 255 +++++-----
app/models/lesson.rb | 76 +--
app/models/link.rb | 36 +-
app/models/mampf_expression.rb | 2 +-
app/models/mampf_matrix.rb | 5 +-
app/models/mampf_set.rb | 2 +-
app/models/mampf_tuple.rb | 2 +-
app/models/manuscript.rb | 45 +-
app/models/medium.rb | 382 +++++++++------
app/models/medium_publisher.rb | 1 +
app/models/notification.rb | 20 +-
app/models/notion.rb | 9 +-
app/models/probe.rb | 15 +-
app/models/program.rb | 24 +-
app/models/question.rb | 20 +-
app/models/quiz.rb | 19 +-
app/models/quiz_certificate.rb | 6 +-
app/models/quiz_graph.rb | 28 +-
app/models/quiz_round.rb | 103 ++--
app/models/reader.rb | 4 +-
app/models/referral.rb | 88 ++--
app/models/relation.rb | 57 +--
app/models/section.rb | 78 ++--
app/models/section_tag_join.rb | 2 +-
app/models/solution.rb | 5 +-
app/models/subject.rb | 8 +-
app/models/submission.rb | 176 +++----
app/models/submission_cleaner.rb | 112 ++---
app/models/tag.rb | 62 ++-
app/models/talk.rb | 2 +-
app/models/term.rb | 42 +-
app/models/time_stamp.rb | 43 +-
app/models/tutorial.rb | 23 +-
app/models/user.rb | 172 ++++---
app/models/user_cleaner.rb | 26 +-
app/models/user_submission_join.rb | 31 +-
app/uploaders/correction_uploader.rb | 2 +-
app/uploaders/geogebra_uploader.rb | 2 +-
app/uploaders/pdf_uploader.rb | 10 +-
app/uploaders/submission_uploader.rb | 6 +-
app/uploaders/video_uploader.rb | 4 +-
app/uploaders/vtt_uploader.rb | 2 +-
app/uploaders/zip_uploader.rb | 16 +-
app/validators/http_url_validator.rb | 1 -
app/views/users/list.json.jbuilder | 2 +-
app/workers/cache_cleaner.rb | 2 +-
app/workers/consumption_saver.rb | 2 +-
app/workers/interaction_saver.rb | 8 +-
app/workers/media_publisher.rb | 2 +-
app/workers/metadata_extractor.rb | 3 +-
app/workers/probe_saver.rb | 3 +-
app/workers/submissions_cleaner.rb | 2 +-
app/workers/user_cleaner_job.rb | 2 +-
158 files changed, 3313 insertions(+), 2803 deletions(-)
diff --git a/app/abilities/administration_ability.rb b/app/abilities/administration_ability.rb
index e1b6bb5f1..df640725d 100644
--- a/app/abilities/administration_ability.rb
+++ b/app/abilities/administration_ability.rb
@@ -12,4 +12,4 @@ def initialize(user)
user.admin?
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/announcement_ability.rb b/app/abilities/announcement_ability.rb
index ba171a55a..177f43510 100644
--- a/app/abilities/announcement_ability.rb
+++ b/app/abilities/announcement_ability.rb
@@ -14,7 +14,7 @@ def initialize(user)
can :create, Announcement do |announcement|
user.admin? ||
- (announcement.lecture.present? && user.can_edit?(announcement.lecture))
+ (announcement.lecture.present? && user.can_edit?(announcement.lecture))
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/answer_ability.rb b/app/abilities/answer_ability.rb
index 11b610bba..f4b41b3c1 100644
--- a/app/abilities/answer_ability.rb
+++ b/app/abilities/answer_ability.rb
@@ -10,4 +10,4 @@ def initialize(user)
can :update_answer_box, Answer
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/assignment_ability.rb b/app/abilities/assignment_ability.rb
index 28a85f2eb..2d39c7edd 100644
--- a/app/abilities/assignment_ability.rb
+++ b/app/abilities/assignment_ability.rb
@@ -9,4 +9,4 @@ def initialize(user)
assignment.lecture.present? && user.can_edit?(assignment.lecture)
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/chapter_ability.rb b/app/abilities/chapter_ability.rb
index fecdd083d..2d6cb94b8 100644
--- a/app/abilities/chapter_ability.rb
+++ b/app/abilities/chapter_ability.rb
@@ -9,4 +9,4 @@ def initialize(user)
chapter.lecture.present? && user.can_edit?(chapter.lecture)
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/course_ability.rb b/app/abilities/course_ability.rb
index ea3fba2de..5e3f1545a 100644
--- a/app/abilities/course_ability.rb
+++ b/app/abilities/course_ability.rb
@@ -20,4 +20,4 @@ def initialize(user)
!user.generic? || course.subscribed_by?(user)
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/division_ability.rb b/app/abilities/division_ability.rb
index 0c5339168..c1a38ca88 100644
--- a/app/abilities/division_ability.rb
+++ b/app/abilities/division_ability.rb
@@ -8,4 +8,4 @@ def initialize(user)
user.admin?
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/erdbeere_ability.rb b/app/abilities/erdbeere_ability.rb
index e0ed55d84..f19f32782 100644
--- a/app/abilities/erdbeere_ability.rb
+++ b/app/abilities/erdbeere_ability.rb
@@ -12,4 +12,4 @@ def initialize(user)
!user.generic?
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/interaction_ability.rb b/app/abilities/interaction_ability.rb
index c577971ba..b8dc9f41e 100644
--- a/app/abilities/interaction_ability.rb
+++ b/app/abilities/interaction_ability.rb
@@ -8,4 +8,4 @@ def initialize(user)
user.admin?
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/item_ability.rb b/app/abilities/item_ability.rb
index 7b0052cef..77960bb19 100644
--- a/app/abilities/item_ability.rb
+++ b/app/abilities/item_ability.rb
@@ -6,9 +6,9 @@ def initialize(user)
can [:create, :update, :edit, :destroy], Item do |item|
(item.medium.nil? && !user.generic?) ||
- (item.medium && user.can_edit?(item.medium))
+ (item.medium && user.can_edit?(item.medium))
end
can :display, Item
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/lecture_ability.rb b/app/abilities/lecture_ability.rb
index 5480923c4..4794e679c 100644
--- a/app/abilities/lecture_ability.rb
+++ b/app/abilities/lecture_ability.rb
@@ -36,4 +36,4 @@ def initialize(user)
lecture.published? || !user.generic?
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/lesson_ability.rb b/app/abilities/lesson_ability.rb
index 0ee9afabd..c1af01c98 100644
--- a/app/abilities/lesson_ability.rb
+++ b/app/abilities/lesson_ability.rb
@@ -12,4 +12,4 @@ def initialize(user)
user.can_edit?(lesson)
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/main_ability.rb b/app/abilities/main_ability.rb
index bd65084b6..7ced6bc32 100644
--- a/app/abilities/main_ability.rb
+++ b/app/abilities/main_ability.rb
@@ -4,4 +4,4 @@ class MainAbility
def initialize(user)
can :start, :main
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/medium_ability.rb b/app/abilities/medium_ability.rb
index 1a39a4d36..f173dd07c 100644
--- a/app/abilities/medium_ability.rb
+++ b/app/abilities/medium_ability.rb
@@ -8,8 +8,8 @@ def initialize(user)
can [:index, :new, :search], Medium
can [:show, :show_comments], Medium do |medium|
- medium.visible_for_user?(user) &&
- !(medium.sort.in?(['Question', 'Remark']) && !user.can_edit?(medium))
+ medium.visible_for_user?(user) &&
+ !(medium.sort.in?(['Question', 'Remark']) && !user.can_edit?(medium))
end
can :inspect, Medium do |medium|
@@ -39,7 +39,7 @@ def initialize(user)
# guest users can play/display media when their release status 'all'
can [:play, :display, :geogebra], Medium do |medium|
(!user.new_record? && medium.visible_for_user?(user)) ||
- medium.free?
+ medium.free?
end
can :update_tags, Medium do |medium|
@@ -50,4 +50,4 @@ def initialize(user)
!user.new_record?
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/notification_ability.rb b/app/abilities/notification_ability.rb
index 89fe5d7d1..a3b9abd0c 100644
--- a/app/abilities/notification_ability.rb
+++ b/app/abilities/notification_ability.rb
@@ -11,4 +11,4 @@ def initialize(user)
notification.recipient == user
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/profile_ability.rb b/app/abilities/profile_ability.rb
index 9370bbc77..3000ca054 100644
--- a/app/abilities/profile_ability.rb
+++ b/app/abilities/profile_ability.rb
@@ -8,4 +8,4 @@ def initialize(user)
:toggle_thread_subscription, :subscribe_lecture, :unsubscribe_lecture,
:star_lecture, :unstar_lecture, :show_accordion, :request_data], :profile
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/program_ability.rb b/app/abilities/program_ability.rb
index 4b691a242..50c586533 100644
--- a/app/abilities/program_ability.rb
+++ b/app/abilities/program_ability.rb
@@ -8,4 +8,4 @@ def initialize(user)
user.admin?
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/question_ability.rb b/app/abilities/question_ability.rb
index c921d7fca..1d20d8d27 100644
--- a/app/abilities/question_ability.rb
+++ b/app/abilities/question_ability.rb
@@ -10,4 +10,4 @@ def initialize(user)
user.can_edit?(question)
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/quiz_ability.rb b/app/abilities/quiz_ability.rb
index 57372048e..4032d5125 100644
--- a/app/abilities/quiz_ability.rb
+++ b/app/abilities/quiz_ability.rb
@@ -13,4 +13,4 @@ def initialize(user)
quiz && user.can_edit?(quiz.becomes(Medium))
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/quiz_certificate_ability.rb b/app/abilities/quiz_certificate_ability.rb
index 206827a25..31bca228f 100644
--- a/app/abilities/quiz_certificate_ability.rb
+++ b/app/abilities/quiz_certificate_ability.rb
@@ -10,4 +10,4 @@ def initialize(user)
user.tutor? || !user.generic?
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/referral_ability.rb b/app/abilities/referral_ability.rb
index 08bbd413e..138ba4df7 100644
--- a/app/abilities/referral_ability.rb
+++ b/app/abilities/referral_ability.rb
@@ -12,4 +12,4 @@ def initialize(user)
!user.generic? || user.media_editor?
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/remark_ability.rb b/app/abilities/remark_ability.rb
index 846798578..63b4810e7 100644
--- a/app/abilities/remark_ability.rb
+++ b/app/abilities/remark_ability.rb
@@ -8,4 +8,4 @@ def initialize(user)
user.can_edit?(remark)
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/search_ability.rb b/app/abilities/search_ability.rb
index 499fee1bc..018392d85 100644
--- a/app/abilities/search_ability.rb
+++ b/app/abilities/search_ability.rb
@@ -6,4 +6,4 @@ def initialize(user)
can :index, :search
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/section_ability.rb b/app/abilities/section_ability.rb
index 1182aece4..215b19c34 100644
--- a/app/abilities/section_ability.rb
+++ b/app/abilities/section_ability.rb
@@ -13,4 +13,4 @@ def initialize(user)
user.can_edit?(section.lecture)
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/subject_ability.rb b/app/abilities/subject_ability.rb
index 9dd2944e3..4961d65ef 100644
--- a/app/abilities/subject_ability.rb
+++ b/app/abilities/subject_ability.rb
@@ -8,4 +8,4 @@ def initialize(user)
user.admin?
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/submission_ability.rb b/app/abilities/submission_ability.rb
index d3ffaeff1..5905c72a0 100644
--- a/app/abilities/submission_ability.rb
+++ b/app/abilities/submission_ability.rb
@@ -19,9 +19,9 @@ def initialize(user)
end
can [:show_manuscript, :show_correction], Submission do |submission|
- user.in?(submission.users) || user.in?(submission.tutorial.tutors) ||
- user.in?(submission.tutorial.lecture.editors) ||
- user == submission.tutorial.lecture.teacher
+ user.in?(submission.users) || user.in?(submission.tutorial.tutors) ||
+ user.in?(submission.tutorial.lecture.editors) ||
+ user == submission.tutorial.lecture.teacher
end
end
end
diff --git a/app/abilities/tag_ability.rb b/app/abilities/tag_ability.rb
index 0ddad1cf6..c04cd4c90 100644
--- a/app/abilities/tag_ability.rb
+++ b/app/abilities/tag_ability.rb
@@ -13,4 +13,3 @@ def initialize(user)
end
end
end
-
diff --git a/app/abilities/term_ability.rb b/app/abilities/term_ability.rb
index 6daba388d..51a20e8af 100644
--- a/app/abilities/term_ability.rb
+++ b/app/abilities/term_ability.rb
@@ -9,4 +9,4 @@ def initialize(user)
user.admin?
end
end
-end
\ No newline at end of file
+end
diff --git a/app/abilities/tutorial_ability.rb b/app/abilities/tutorial_ability.rb
index d17014db1..fa6087ac6 100644
--- a/app/abilities/tutorial_ability.rb
+++ b/app/abilities/tutorial_ability.rb
@@ -20,7 +20,7 @@ def initialize(user)
can [:bulk_download_submissions, :bulk_download_corrections, :bulk_upload,
:export_teams], Tutorial do |tutorial|
user.in?(tutorial.tutors) ||
- user.editor_or_teacher_in?(tutorial.lecture)
+ user.editor_or_teacher_in?(tutorial.lecture)
end
can :validate_certificate, Tutorial do
@@ -28,7 +28,3 @@ def initialize(user)
end
end
end
-
-
-
-
diff --git a/app/abilities/watchlist_ability.rb b/app/abilities/watchlist_ability.rb
index 67fb84bec..9b7c89044 100644
--- a/app/abilities/watchlist_ability.rb
+++ b/app/abilities/watchlist_ability.rb
@@ -20,4 +20,4 @@ def initialize(user)
entries.all? { |entry| entry&.in?(watchlist.watchlist_entries) }
end
end
-end
\ No newline at end of file
+end
diff --git a/app/controllers/announcements_controller.rb b/app/controllers/announcements_controller.rb
index 454cb6e03..ba3492fff 100644
--- a/app/controllers/announcements_controller.rb
+++ b/app/controllers/announcements_controller.rb
@@ -55,49 +55,50 @@ def expel
private
- def announcement_params
- params.require(:announcement).permit(:details, :lecture_id, :on_main_page)
- end
+ def announcement_params
+ params.require(:announcement).permit(:details, :lecture_id, :on_main_page)
+ end
- def create_notifications
- users_to_notify = if @announcement.lecture.present?
- @announcement.lecture.users
- else
- User
- end
- notifications = []
- users_to_notify.update_all(updated_at: Time.now)
- users_to_notify.find_each do |u|
- notifications << Notification.new(recipient: u,
- notifiable_id: @announcement.id,
- notifiable_type: 'Announcement',
- action: 'create')
+ def create_notifications
+ users_to_notify = if @announcement.lecture.present?
+ @announcement.lecture.users
+ else
+ User
+ end
+ notifications = []
+ users_to_notify.update_all(updated_at: Time.now)
+ users_to_notify.find_each do |u|
+ notifications << Notification.new(recipient: u,
+ notifiable_id: @announcement.id,
+ notifiable_type: 'Announcement',
+ action: 'create')
+ end
+ # use activerecord-import gem to use only one SQL instruction
+ Notification.import notifications
end
- # use activerecord-import gem to use only one SQL instruction
- Notification.import notifications
- end
- def send_notification_email
- recipients = if @announcement.lecture.present?
- @announcement.lecture.users
- .where(email_for_announcement: true)
- else
- User.where(email_for_news: true)
- end
- I18n.available_locales.each do |l|
- local_recipients = recipients.where(locale: l)
- if local_recipients.any?
- NotificationMailer.with(recipients: local_recipients.pluck(:id),
- locale: l,
- announcement: @announcement)
- .announcement_email.deliver_later
+ def send_notification_email
+ recipients = if @announcement.lecture.present?
+ @announcement.lecture.users
+ .where(email_for_announcement: true)
+ else
+ User.where(email_for_news: true)
+ end
+ I18n.available_locales.each do |l|
+ local_recipients = recipients.where(locale: l)
+ if local_recipients.any?
+ NotificationMailer.with(recipients: local_recipients.pluck(:id),
+ locale: l,
+ announcement: @announcement)
+ .announcement_email.deliver_later
+ end
end
end
- end
- def set_announcement
- @announcement = Announcement.find_by_id(params[:id])
- return if @announcement.present?
- redirect_to :root, alert: I18n.t('controllers.no_announcement')
- end
+ def set_announcement
+ @announcement = Announcement.find_by_id(params[:id])
+ return if @announcement.present?
+
+ redirect_to :root, alert: I18n.t('controllers.no_announcement')
+ end
end
diff --git a/app/controllers/answers_controller.rb b/app/controllers/answers_controller.rb
index 0b5ec5916..8e0441d4d 100644
--- a/app/controllers/answers_controller.rb
+++ b/app/controllers/answers_controller.rb
@@ -19,6 +19,7 @@ def create
authorize! :create, @answer
I18n.locale = @answer.question&.locale_with_inheritance
return unless @answer.save
+
@success = true
end
@@ -29,6 +30,7 @@ def update
def destroy
@id = params[:id]
return unless @answer.destroy
+
@success = true
end
@@ -39,13 +41,14 @@ def update_answer_box
private
- def set_answer
- @answer = Answer.find_by_id(params[:id])
- return if @answer.present?
- redirect_to root_path, alert: I18n.t('controllers.no_answer')
- end
+ def set_answer
+ @answer = Answer.find_by_id(params[:id])
+ return if @answer.present?
- def answer_params
- params.require(:answer).permit(:text, :value, :explanation, :question_id)
- end
+ redirect_to root_path, alert: I18n.t('controllers.no_answer')
+ end
+
+ def answer_params
+ params.require(:answer).permit(:text, :value, :explanation, :question_id)
+ end
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 76550fadb..a19c8553f 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -9,13 +9,13 @@ class ApplicationController < ActionController::Base
before_action :set_locale
after_action :store_interaction, if: :user_signed_in?
-
etag { current_user.try :id }
def current_user
- unless controller_name == 'administration' && action_name == 'index'
+ unless controller_name == 'administration' && action_name == 'index'
return super
end
+
@current_user ||= super.tap do |user|
::ActiveRecord::Associations::Preloader.new(records: [user],
associations:
@@ -46,7 +46,7 @@ def current_user
rescue_from ActionController::InvalidAuthenticityToken do
redirect_to main_app.root_url,
- alert: I18n.t('controllers.session_expired')
+ alert: I18n.t('controllers.session_expired')
end
# determine where to send the user after login
@@ -69,65 +69,69 @@ def prevent_caching
protected
- def configure_permitted_parameters
- # add additional paramters to registration
- devise_parameter_sanitizer.permit(:sign_up, keys: [:locale, :consents])
- end
+ def configure_permitted_parameters
+ # add additional paramters to registration
+ devise_parameter_sanitizer.permit(:sign_up, keys: [:locale, :consents])
+ end
private
- # It's important that the location is NOT stored if:
- # - The request method is not GET (non idempotent)
- # - The request is handled by a Devise controller such as
- # Devise::SessionsController as that could cause an
- # infinite redirect loop.
- # - The request is an Ajax request as this can lead to very
- # unexpected behaviour.
- def storable_location?
- request.get? && is_navigational_format? && !devise_controller? &&
- !request.xhr?
- end
+ # It's important that the location is NOT stored if:
+ # - The request method is not GET (non idempotent)
+ # - The request is handled by a Devise controller such as
+ # Devise::SessionsController as that could cause an
+ # infinite redirect loop.
+ # - The request is an Ajax request as this can lead to very
+ # unexpected behaviour.
+ def storable_location?
+ request.get? && is_navigational_format? && !devise_controller? &&
+ !request.xhr?
+ end
- def store_user_location!
- # :user is the scope we are authenticating
- store_location_for(:user, request.fullpath)
- end
+ def store_user_location!
+ # :user is the scope we are authenticating
+ store_location_for(:user, request.fullpath)
+ end
- def set_locale
- I18n.locale = current_user.try(:locale) || locale_param ||
+ def set_locale
+ I18n.locale = current_user.try(:locale) || locale_param ||
cookie_locale_param || I18n.default_locale
- unless user_signed_in?
- cookies[:locale] = I18n.locale
+ unless user_signed_in?
+ cookies[:locale] = I18n.locale
+ end
end
- end
- def store_interaction
- return if controller_name.in?(['sessions', 'administration', 'users',
- 'events', 'interactions', 'profile',
- 'clickers', 'clicker_votes', 'registrations'])
- return if controller_name == 'main' && action_name == 'home'
- return if controller_name == 'tags' && action_name.in?(['fill_tag_select', 'fill_course_tags'])
- study_participant = current_user.anonymized_id if current_user.study_participant
- # as of Rack 2.0.8, the session_id is wrapped in a class of its own
- # it is not a string anymore
- # see https://github.com/rack/rack/issues/1433
- InteractionSaver.perform_async(request.session_options[:id].public_id,
- request.original_fullpath,
- request.referrer,
- study_participant)
- end
+ def store_interaction
+ return if controller_name.in?(['sessions', 'administration', 'users',
+ 'events', 'interactions', 'profile',
+ 'clickers', 'clicker_votes', 'registrations'])
+ return if controller_name == 'main' && action_name == 'home'
+ return if controller_name == 'tags' && action_name.in?(['fill_tag_select',
+ 'fill_course_tags'])
+
+ study_participant = current_user.anonymized_id if current_user.study_participant
+ # as of Rack 2.0.8, the session_id is wrapped in a class of its own
+ # it is not a string anymore
+ # see https://github.com/rack/rack/issues/1433
+ InteractionSaver.perform_async(request.session_options[:id].public_id,
+ request.original_fullpath,
+ request.referrer,
+ study_participant)
+ end
- def locale_param
- return unless params[:locale].in?(available_locales)
- params[:locale]
- end
+ def locale_param
+ return unless params[:locale].in?(available_locales)
- def cookie_locale_param
- return unless cookies[:locale].in?(available_locales)
- cookies[:locale]
- end
+ params[:locale]
+ end
- def available_locales
- I18n.available_locales.map(&:to_s)
- end
+ def cookie_locale_param
+ return unless cookies[:locale].in?(available_locales)
+
+ cookies[:locale]
+ end
+
+ def available_locales
+ I18n.available_locales.map(&:to_s)
+ end
end
diff --git a/app/controllers/assignments_controller.rb b/app/controllers/assignments_controller.rb
index 6dd2a2ad3..9f2b97f09 100644
--- a/app/controllers/assignments_controller.rb
+++ b/app/controllers/assignments_controller.rb
@@ -32,6 +32,7 @@ def update
@assignment.update(assignment_params)
@errors = @assignment.errors
return if @errors.present?
+
@assignment.update(medium: nil) if assignment_params[:medium_id].blank?
end
@@ -52,27 +53,29 @@ def cancel_new
private
- def set_assignment
- @assignment = Assignment.find_by_id(params[:id])
- @lecture = @assignment&.lecture
- set_assignment_locale and return if @assignment
- redirect_to :root, alert: I18n.t('controllers.no_assignment')
- end
+ def set_assignment
+ @assignment = Assignment.find_by_id(params[:id])
+ @lecture = @assignment&.lecture
+ set_assignment_locale and return if @assignment
- def set_lecture
- @lecture = Lecture.find_by_id(assignment_params[:lecture_id])
- return if @lecture
- redirect_to :root, alert: I18n.t('controllers.no_lecture')
- end
+ redirect_to :root, alert: I18n.t('controllers.no_assignment')
+ end
+
+ def set_lecture
+ @lecture = Lecture.find_by_id(assignment_params[:lecture_id])
+ return if @lecture
- def set_assignment_locale
- I18n.locale = @lecture&.locale_with_inheritance || current_user.locale ||
+ redirect_to :root, alert: I18n.t('controllers.no_lecture')
+ end
+
+ def set_assignment_locale
+ I18n.locale = @lecture&.locale_with_inheritance || current_user.locale ||
I18n.default_locale
- end
+ end
- def assignment_params
- params.require(:assignment).permit(:title, :medium_id, :lecture_id,
- :deadline, :accepted_file_type,
- :deletion_date)
- end
-end
\ No newline at end of file
+ def assignment_params
+ params.require(:assignment).permit(:title, :medium_id, :lecture_id,
+ :deadline, :accepted_file_type,
+ :deletion_date)
+ end
+end
diff --git a/app/controllers/chapters_controller.rb b/app/controllers/chapters_controller.rb
index 60e3ce7ab..1b6188a3c 100644
--- a/app/controllers/chapters_controller.rb
+++ b/app/controllers/chapters_controller.rb
@@ -15,7 +15,7 @@ def edit
def update
I18n.locale = @chapter.lecture.locale_with_inheritance ||
- current_user.locale || I18n.default_locale
+ current_user.locale || I18n.default_locale
@chapter.update(chapter_params)
if @chapter.valid?
predecessor = params[:chapter][:predecessor]
@@ -35,7 +35,7 @@ def create
@chapter = Chapter.new(chapter_params)
authorize! :create, @chapter
I18n.locale = @chapter&.lecture&.locale_with_inheritance ||
- current_user.locale || I18n.default_locale
+ current_user.locale || I18n.default_locale
position = params[:chapter][:predecessor]
# place the chapter in the correct position
if position.present?
@@ -52,7 +52,7 @@ def new
@chapter = Chapter.new(lecture: @lecture)
authorize! :new, @chapter
I18n.locale = @chapter.lecture.locale_with_inheritance ||
- current_user.locale || I18n.default_locale
+ current_user.locale || I18n.default_locale
end
def destroy
@@ -68,19 +68,20 @@ def list_sections
private
- def set_chapter
- @chapter = Chapter.find_by_id(params[:id])
- return if @chapter.present?
- redirect_to :root, alert: I18n.t('controllers.no_chapter')
- end
+ def set_chapter
+ @chapter = Chapter.find_by_id(params[:id])
+ return if @chapter.present?
- def chapter_params
- params.require(:chapter).permit(:title, :display_number, :lecture_id,
- :hidden, :details)
- end
+ redirect_to :root, alert: I18n.t('controllers.no_chapter')
+ end
- def set_view_locale
- I18n.locale = @chapter.lecture.locale_with_inheritance ||
+ def chapter_params
+ params.require(:chapter).permit(:title, :display_number, :lecture_id,
+ :hidden, :details)
+ end
+
+ def set_view_locale
+ I18n.locale = @chapter.lecture.locale_with_inheritance ||
current_user.locale || I18n.default_locale
- end
+ end
end
diff --git a/app/controllers/clicker_votes_controller.rb b/app/controllers/clicker_votes_controller.rb
index 5ed76326b..d2b684e04 100644
--- a/app/controllers/clicker_votes_controller.rb
+++ b/app/controllers/clicker_votes_controller.rb
@@ -16,7 +16,7 @@ def create
private
- def vote_params
- params.require(:clicker_vote).permit(:clicker_id, :value)
- end
+ def vote_params
+ params.require(:clicker_vote).permit(:clicker_id, :value)
+ end
end
diff --git a/app/controllers/clickers_controller.rb b/app/controllers/clickers_controller.rb
index e517ff421..55ced38b8 100644
--- a/app/controllers/clickers_controller.rb
+++ b/app/controllers/clickers_controller.rb
@@ -112,20 +112,21 @@ def render_clickerizable_actions
private
- def clicker_params
- params.require(:clicker).permit(:editor_id, :teachable_type,
- :teachable_id, :question_id, :title)
- end
+ def clicker_params
+ params.require(:clicker).permit(:editor_id, :teachable_type,
+ :teachable_id, :question_id, :title)
+ end
- def code_params
- params.permit(:code)
- end
+ def code_params
+ params.permit(:code)
+ end
- def set_clicker
- @clicker = Clicker.find_by_id(params[:id])
- @code = user_signed_in? ? nil : @clicker&.code
- @entered_code = code_params[:code]
- return if @clicker
- redirect_to :root, alert: I18n.t('controllers.no_clicker')
- end
-end
\ No newline at end of file
+ def set_clicker
+ @clicker = Clicker.find_by_id(params[:id])
+ @code = user_signed_in? ? nil : @clicker&.code
+ @entered_code = code_params[:code]
+ return if @clicker
+
+ redirect_to :root, alert: I18n.t('controllers.no_clicker')
+ end
+end
diff --git a/app/controllers/confirmations_controller.rb b/app/controllers/confirmations_controller.rb
index 8acec71a3..b0fd5e1ed 100644
--- a/app/controllers/confirmations_controller.rb
+++ b/app/controllers/confirmations_controller.rb
@@ -1,9 +1,8 @@
class ConfirmationsController < Devise::ConfirmationsController
-
private
- def after_confirmation_path_for(resource_name, resource)
- sign_in(resource) # In case you want to sign in the user
- edit_profile_path
- end
-end
\ No newline at end of file
+ def after_confirmation_path_for(resource_name, resource)
+ sign_in(resource) # In case you want to sign in the user
+ edit_profile_path
+ end
+end
diff --git a/app/controllers/courses_controller.rb b/app/controllers/courses_controller.rb
index bc28a96c8..67be24754 100644
--- a/app/controllers/courses_controller.rb
+++ b/app/controllers/courses_controller.rb
@@ -21,6 +21,7 @@ def update
@course.update(course_params)
@errors = @course.errors
return unless @errors.empty?
+
@course.update(image: nil) if params[:course][:detach_image] == 'true'
changed_image = @course.image_data != old_image_data
if @course.image.present? && changed_image
@@ -56,7 +57,8 @@ def destroy
def take_random_quiz
tags = Tag.where(id: random_quiz_params[:search_course_tag_ids])
- random_quiz = @course.create_random_quiz!(tags, random_quiz_params[:random_quiz_count].to_i)
+ random_quiz = @course.create_random_quiz!(tags,
+ random_quiz_params[:random_quiz_count].to_i)
redirect_to take_quiz_path(random_quiz)
end
@@ -72,70 +74,73 @@ def search
results = search.results
@total = search.total
@courses = Kaminari.paginate_array(results, total_count: @total)
- .page(params[:page]).per(search_params[:per])
+ .page(params[:page]).per(search_params[:per])
end
private
- def set_course
- @course = Course.find_by_id(params[:id])
- return if @course.present?
- redirect_to :root, alert: I18n.t('controllers.no_course')
- end
+ def set_course
+ @course = Course.find_by_id(params[:id])
+ return if @course.present?
- def set_course_admin
- @course = Course.find_by_id(params[:id])
- return if @course.present?
- redirect_to administration_path
- end
+ redirect_to :root, alert: I18n.t('controllers.no_course')
+ end
- def course_params
- params.require(:course).permit(:title, :short_title, :organizational,
- :organizational_concept, :locale,
- :term_independent, :image,
- tag_ids: [],
- preceding_course_ids: [],
- editor_ids: [],
- division_ids: [])
- end
+ def set_course_admin
+ @course = Course.find_by_id(params[:id])
+ return if @course.present?
- def tag_params
- params.permit(:count, tag_ids: [])
- end
+ redirect_to administration_path
+ end
- def search_params
- params.require(:search).permit(:all_editors, :all_programs, :fulltext,
- :term_independent, :per,
- editor_ids: [],
- program_ids: [])
- end
+ def course_params
+ params.require(:course).permit(:title, :short_title, :organizational,
+ :organizational_concept, :locale,
+ :term_independent, :image,
+ tag_ids: [],
+ preceding_course_ids: [],
+ editor_ids: [],
+ division_ids: [])
+ end
- def random_quiz_params
- params.require(:quiz).permit(:random_quiz_count,
- search_course_tag_ids: [])
- end
+ def tag_params
+ params.permit(:count, tag_ids: [])
+ end
- # destroy all notifications related to this course
- def destroy_notifications
- Notification.where(notifiable_id: @course.id, notifiable_type: 'Course')
- .delete_all
- end
+ def search_params
+ params.require(:search).permit(:all_editors, :all_programs, :fulltext,
+ :term_independent, :per,
+ editor_ids: [],
+ program_ids: [])
+ end
- # fill organizational_concept with default view
- def set_organizational_defaults
- @course.update(organizational_concept:
- render_to_string(partial: 'courses/' \
- 'organizational_default',
- formats: :html,
- layout: false))
- end
+ def random_quiz_params
+ params.require(:quiz).permit(:random_quiz_count,
+ search_course_tag_ids: [])
+ end
- def check_if_enough_questions
- return if @course.enough_questions?
- redirect_to :root, alert: I18n.t('controllers.no_test')
- end
+ # destroy all notifications related to this course
+ def destroy_notifications
+ Notification.where(notifiable_id: @course.id, notifiable_type: 'Course')
+ .delete_all
+ end
- def check_for_consent
- redirect_to consent_profile_path unless current_user.consents
- end
+ # fill organizational_concept with default view
+ def set_organizational_defaults
+ @course.update(organizational_concept:
+ render_to_string(partial: 'courses/' \
+ 'organizational_default',
+ formats: :html,
+ layout: false))
+ end
+
+ def check_if_enough_questions
+ return if @course.enough_questions?
+
+ redirect_to :root, alert: I18n.t('controllers.no_test')
+ end
+
+ def check_for_consent
+ redirect_to consent_profile_path unless current_user.consents
+ end
end
diff --git a/app/controllers/divisions_controller.rb b/app/controllers/divisions_controller.rb
index c683c4d0f..9c8ecdd53 100644
--- a/app/controllers/divisions_controller.rb
+++ b/app/controllers/divisions_controller.rb
@@ -7,42 +7,42 @@ def current_ability
@current_ability ||= DivisionAbility.new(current_user)
end
- def edit
- end
+ def edit
+ end
- def new
- @division = Division.new(program_id: params[:program_id].to_i)
+ def new
+ @division = Division.new(program_id: params[:program_id].to_i)
authorize! :new, @division
- end
+ end
- def update
- @division.update(division_params)
- redirect_to classification_path
- end
+ def update
+ @division.update(division_params)
+ redirect_to classification_path
+ end
- def create
- @division = Division.new(division_params)
- @division.program_id = params[:division][:program_id]
+ def create
+ @division = Division.new(division_params)
+ @division.program_id = params[:division][:program_id]
authorize! :create, @division
- @division.save
- redirect_to classification_path
- end
+ @division.save
+ redirect_to classification_path
+ end
- def destroy
- @division.destroy
- redirect_to classification_path
- end
+ def destroy
+ @division.destroy
+ redirect_to classification_path
+ end
private
- def set_division
- @division = Division.find_by_id(params[:id])
- return if @division.present?
+ def set_division
+ @division = Division.find_by_id(params[:id])
+ return if @division.present?
- redirect_to root_path, alert: I18n.t('controllers.no_division')
- end
+ redirect_to root_path, alert: I18n.t('controllers.no_division')
+ end
- def division_params
- params.require(:division).permit(*Division.globalize_attribute_names)
- end
-end
\ No newline at end of file
+ def division_params
+ params.require(:division).permit(*Division.globalize_attribute_names)
+ end
+end
diff --git a/app/controllers/erdbeere_controller.rb b/app/controllers/erdbeere_controller.rb
index 22081e47c..d880b9114 100644
--- a/app/controllers/erdbeere_controller.rb
+++ b/app/controllers/erdbeere_controller.rb
@@ -1,46 +1,46 @@
# ExamplesController
class ErdbeereController < ApplicationController
authorize_resource class: false
- layout 'application'
+ layout 'application'
def current_ability
@current_ability ||= ErdbeereAbility.new(current_user)
end
- def show_example
+ def show_example
response = Faraday.get(ENV['ERDBEERE_API'] + "/examples/#{params[:id]}")
@content = if response.status == 200
- JSON.parse(response.body)['embedded_html']
- else
- 'Something went wrong.'
- end
- end
+ JSON.parse(response.body)['embedded_html']
+ else
+ 'Something went wrong.'
+ end
+ end
- def show_property
+ def show_property
response = Faraday.get(ENV['ERDBEERE_API'] + "/properties/#{params[:id]}")
- @content = if response.status == 200
- JSON.parse(response.body)['embedded_html']
- else
- 'Something went wrong.'
- end
- end
+ @content = if response.status == 200
+ JSON.parse(response.body)['embedded_html']
+ else
+ 'Something went wrong.'
+ end
+ end
- def show_structure
- id = params[:id]
+ def show_structure
+ id = params[:id]
response = Faraday.get(ENV['ERDBEERE_API'] + "/structures/#{params[:id]}")
@content = if response.status == 200
- JSON.parse(response.body)['embedded_html']
- else
- 'Something went wrong.'
- end
- end
+ JSON.parse(response.body)['embedded_html']
+ else
+ 'Something went wrong.'
+ end
+ end
- def find_tags
- @sort = params[:sort]
- @id = params[:id].to_i
- @tags = Tag.find_erdbeere_tags(@sort, @id)
- end
+ def find_tags
+ @sort = params[:sort]
+ @id = params[:id].to_i
+ @tags = Tag.find_erdbeere_tags(@sort, @id)
+ end
def edit_tags
end
@@ -59,11 +59,11 @@ def display_info
return
end
@info = if @sort == 'Structure'
- @content['data']['attributes']['name']
- else
- "#{@content['included'][0]['attributes']['name']}:"\
- "#{@content['data']['attributes']['name']}"
- end
+ @content['data']['attributes']['name']
+ else
+ "#{@content['included'][0]['attributes']['name']}:"\
+ "#{@content['data']['attributes']['name']}"
+ end
end
def update_tags
@@ -93,7 +93,9 @@ def fill_realizations_select
@structures = hash['data'].map do |d|
{ id: d['id'],
name: d['attributes']['name'],
- properties: d['relationships']['original_properties']['data'].map { |x| x['id'] }}
+ properties: d['relationships']['original_properties']['data'].map { |x|
+ x['id']
+ } }
end
@properties = hash['included'].map do |d|
{ id: d['id'],
@@ -104,21 +106,21 @@ def fill_realizations_select
def find_example
response = Faraday.get(ENV['ERDBEERE_API'] + '/find?' + find_params.to_query)
@content = if response.status == 200
- JSON.parse(response.body)['embedded_html']
- else
- 'Something went wrong.'
- end
+ JSON.parse(response.body)['embedded_html']
+ else
+ 'Something went wrong.'
+ end
end
private
- def erdbeere_params
- params.require(:erdbeere).permit(:sort, :id, tag_ids: [])
- end
+ def erdbeere_params
+ params.require(:erdbeere).permit(:sort, :id, tag_ids: [])
+ end
- def find_params
- params.require(:find).permit(:structure_id,
- satisfies: [],
- violates: [])
- end
-end
\ No newline at end of file
+ def find_params
+ params.require(:find).permit(:structure_id,
+ satisfies: [],
+ violates: [])
+ end
+end
diff --git a/app/controllers/interactions_controller.rb b/app/controllers/interactions_controller.rb
index 5892ed34b..81242996b 100644
--- a/app/controllers/interactions_controller.rb
+++ b/app/controllers/interactions_controller.rb
@@ -7,30 +7,34 @@ def index
end
def export_interactions
- start_date = interaction_params[:start_date].to_date
- end_date = interaction_params[:end_date].to_date
- @interactions = Interaction.created_between(start_date, end_date)
+ start_date = interaction_params[:start_date].to_date
+ end_date = interaction_params[:end_date].to_date
+ @interactions = Interaction.created_between(start_date, end_date)
respond_to do |format|
format.html { head :ok }
- format.csv { send_data @interactions.to_csv,
- filename: "interactions-from-#{start_date}-to-#{end_date}-at-#{Time.now}.csv" }
+ format.csv {
+ send_data @interactions.to_csv,
+ filename: "interactions-from-#{start_date}-to-#{end_date}-at-#{Time.now}.csv"
+ }
end
end
def export_probes
- start_date = interaction_params[:start_date].to_date
- end_date = interaction_params[:end_date].to_date
- @probes = Probe.created_between(start_date, end_date)
+ start_date = interaction_params[:start_date].to_date
+ end_date = interaction_params[:end_date].to_date
+ @probes = Probe.created_between(start_date, end_date)
respond_to do |format|
format.html { head :ok }
- format.csv { send_data @probes.to_csv,
- filename: "probes-from-#{start_date}-to-#{end_date}-at-#{Time.now}.csv" }
+ format.csv {
+ send_data @probes.to_csv,
+ filename: "probes-from-#{start_date}-to-#{end_date}-at-#{Time.now}.csv"
+ }
end
end
private
- def interaction_params
- params.require(:interactions).permit(:start_date, :end_date)
- end
-end
\ No newline at end of file
+ def interaction_params
+ params.require(:interactions).permit(:start_date, :end_date)
+ end
+end
diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb
index 67ec44559..56c0bf885 100644
--- a/app/controllers/items_controller.rb
+++ b/app/controllers/items_controller.rb
@@ -50,27 +50,28 @@ def display
private
- def set_item
- @item = Item.find(params[:id])
- end
+ def set_item
+ @item = Item.find(params[:id])
+ end
+
+ def set_explanation
+ if @referral_id.zero? || @item != Referral.find(@referral_id).item
+ return @item.explanation
+ end
- def set_explanation
- if @referral_id.zero? || @item != Referral.find(@referral_id).item
- return @item.explanation
+ Referral.find(@referral_id).explanation
end
- Referral.find(@referral_id).explanation
- end
- def item_params
- # params are cloned and then start time is converted to a TimeStamp object
- filter = params.require(:item).permit(:sort, :start_time, :section_id,
- :medium_id, :ref_number, :description,
- :link, :page, :pdf_destination,
- :explanation, :hidden).clone
- if filter[:medium_id].present?
- filter[:start_time] = TimeStamp.new(time_string: filter[:start_time])
+ def item_params
+ # params are cloned and then start time is converted to a TimeStamp object
+ filter = params.require(:item).permit(:sort, :start_time, :section_id,
+ :medium_id, :ref_number, :description,
+ :link, :page, :pdf_destination,
+ :explanation, :hidden).clone
+ if filter[:medium_id].present?
+ filter[:start_time] = TimeStamp.new(time_string: filter[:start_time])
+ end
+ filter[:section_id] = nil if filter[:section_id] == ''
+ filter
end
- filter[:section_id] = nil if filter[:section_id] == ''
- filter
- end
end
diff --git a/app/controllers/lectures_controller.rb b/app/controllers/lectures_controller.rb
index bf7a63ffb..bf1aab76c 100644
--- a/app/controllers/lectures_controller.rb
+++ b/app/controllers/lectures_controller.rb
@@ -44,11 +44,11 @@ def update
.new_editor_email.deliver_later
end
end
-
+
@lecture.update(lecture_params)
if structure_params.present?
structure_ids = structure_params.select { |_k, v| v.to_i == 1 }.keys
- .map(&:to_i)
+ .map(&:to_i)
@lecture.update(structure_ids: structure_ids)
end
@lecture.touch
@@ -74,7 +74,8 @@ def show
chapters: [:lecture,
sections: [lessons: [:tags],
chapter: [:lecture],
- tags: [:notions, :lessons]]])
+ tags: [:notions,
+ :lessons]]])
.find_by_id(params[:id])
@notifications = current_user.active_notifications(@lecture)
@new_topics_count = @lecture.unread_forum_topics_count(current_user) || 0
@@ -87,6 +88,7 @@ def new
authorize! :new, @lecture
@from = params[:from]
return unless @from == 'course'
+
# if new action was triggered from inside a course view, add the course
# info to the lecture
@lecture.course = Course.find_by_id(params[:course])
@@ -113,7 +115,7 @@ def create
end
redirect_to edit_course_path(@lecture.course),
notice: I18n.t('controllers.created_lecture_success',
- lecture: @lecture.title_with_teacher)
+ lecture: @lecture.title_with_teacher)
return
end
@errors = @lecture.errors
@@ -247,6 +249,7 @@ def search
@results_as_list = search_params[:results_as_list] == 'true'
return unless @total.zero?
return unless search_params[:fulltext]&.length.to_i > 1
+
@similar_titles = Course.similar_courses(search_params[:fulltext])
end
@@ -267,7 +270,7 @@ def subscribe_page
def import_toc
imported_lecture = Lecture
- .find_by_id(import_toc_params[:imported_lecture_id])
+ .find_by_id(import_toc_params[:imported_lecture_id])
import_sections = import_toc_params[:import_sections] == '1'
import_tags = import_toc_params[:import_tags] == '1'
@lecture.import_toc!(imported_lecture, import_sections, import_tags)
@@ -276,154 +279,157 @@ def import_toc
private
- def set_lecture
- @lecture = Lecture.find_by_id(params[:id])
- return if @lecture
- redirect_to :root, alert: I18n.t('controllers.no_lecture')
- end
+ def set_lecture
+ @lecture = Lecture.find_by_id(params[:id])
+ return if @lecture
- def set_lecture_cookie
- cookies[:current_lecture_id] = @lecture.id
- end
+ redirect_to :root, alert: I18n.t('controllers.no_lecture')
+ end
- def set_view_locale
- I18n.locale = @lecture.locale_with_inheritance || current_user.locale ||
+ def set_lecture_cookie
+ cookies[:current_lecture_id] = @lecture.id
+ end
+
+ def set_view_locale
+ I18n.locale = @lecture.locale_with_inheritance || current_user.locale ||
I18n.default_locale
- end
+ end
- def check_for_consent
- redirect_to consent_profile_path unless current_user.consents
- end
+ def check_for_consent
+ redirect_to consent_profile_path unless current_user.consents
+ end
- def check_for_subscribe
- redirect_to subscribe_lecture_page_path(@lecture.id) unless @lecture.in?(current_user.lectures)
- end
+ def check_for_subscribe
+ redirect_to subscribe_lecture_page_path(@lecture.id) unless @lecture.in?(current_user.lectures)
+ end
- def lecture_params
- params.require(:lecture).permit(:course_id, :term_id, :teacher_id,
- :start_chapter, :absolute_numbering,
- :start_section, :organizational, :locale,
- :organizational_concept, :muesli,
- :organizational_on_top,
- :disable_teacher_display,
- :content_mode, :passphrase, :sort,
- :comments_disabled,
- :submission_max_team_size,
- :submission_grace_period,
- editor_ids: [])
- end
+ def lecture_params
+ params.require(:lecture).permit(:course_id, :term_id, :teacher_id,
+ :start_chapter, :absolute_numbering,
+ :start_section, :organizational, :locale,
+ :organizational_concept, :muesli,
+ :organizational_on_top,
+ :disable_teacher_display,
+ :content_mode, :passphrase, :sort,
+ :comments_disabled,
+ :submission_max_team_size,
+ :submission_grace_period,
+ editor_ids: [])
+ end
- def structure_params
- params.require(:lecture).permit(structures: {})[:structures]
- end
+ def structure_params
+ params.require(:lecture).permit(structures: {})[:structures]
+ end
- def comment_params
- params.require(:lecture).permit(:close_comments)
- end
+ def comment_params
+ params.require(:lecture).permit(:close_comments)
+ end
- def import_toc_params
- params.permit(:imported_lecture_id, :import_sections, :import_tags)
- end
+ def import_toc_params
+ params.permit(:imported_lecture_id, :import_sections, :import_tags)
+ end
- # create notifications to all users about creation of new lecture
- def create_notifications
- notifications = []
- User.find_each do |u|
- notifications << Notification.new(recipient: u,
- notifiable_id: @lecture.id,
- notifiable_type: 'Lecture',
- action: 'create')
+ # create notifications to all users about creation of new lecture
+ def create_notifications
+ notifications = []
+ User.find_each do |u|
+ notifications << Notification.new(recipient: u,
+ notifiable_id: @lecture.id,
+ notifiable_type: 'Lecture',
+ action: 'create')
+ end
+ Notification.import notifications
end
- Notification.import notifications
- end
- def send_notification_email
- recipients = User.where(email_for_teachable: true)
- I18n.available_locales.each do |l|
- local_recipients = recipients.where(locale: l)
- if local_recipients.any?
- NotificationMailer.with(recipients: local_recipients.pluck(:id),
- locale: l,
- lecture: @lecture)
- .new_lecture_email.deliver_later
+ def send_notification_email
+ recipients = User.where(email_for_teachable: true)
+ I18n.available_locales.each do |l|
+ local_recipients = recipients.where(locale: l)
+ if local_recipients.any?
+ NotificationMailer.with(recipients: local_recipients.pluck(:id),
+ locale: l,
+ lecture: @lecture)
+ .new_lecture_email.deliver_later
+ end
end
end
- end
- # destroy all notifications related to this lecture
- def destroy_notifications
- Notification.where(notifiable_id: @lecture.id, notifiable_type: 'Lecture')
- .delete_all
- end
+ # destroy all notifications related to this lecture
+ def destroy_notifications
+ Notification.where(notifiable_id: @lecture.id, notifiable_type: 'Lecture')
+ .delete_all
+ end
- # fill organizational_concept with default view
- def set_organizational_defaults
- partial_path = 'lectures/organizational/'
- partial_path += @lecture.seminar? ? 'seminar' : 'lecture'
- @lecture.update(organizational_concept:
- render_to_string(partial: partial_path,
- formats: :html,
- layout: false))
- end
+ # fill organizational_concept with default view
+ def set_organizational_defaults
+ partial_path = 'lectures/organizational/'
+ partial_path += @lecture.seminar? ? 'seminar' : 'lecture'
+ @lecture.update(organizational_concept:
+ render_to_string(partial: partial_path,
+ formats: :html,
+ layout: false))
+ end
- # set language to default language
- def set_language
- @lecture.update(locale: I18n.default_locale.to_s)
- end
+ # set language to default language
+ def set_language
+ @lecture.update(locale: I18n.default_locale.to_s)
+ end
- def eager_load_stuff
- @lecture = Lecture.includes(:teacher, :term, :editors,
- :announcements, :imported_media,
- course: [:editors],
- media: [:teachable, :tags],
- lessons: [media: [:tags]],
- chapters: [:lecture,
- sections: [lessons: [:tags],
- chapter: [:lecture],
- tags: [:notions, :lessons]]])
- .find_by_id(params[:id])
- @media = @lecture.media_with_inheritance_uncached_eagerload_stuff
- lecture_tags = @lecture.tags
- @course_tags = @lecture.course_tags(lecture_tags: lecture_tags)
- @extra_tags = @lecture.extra_tags(lecture_tags: lecture_tags)
- @deferred_tags = @lecture.deferred_tags(lecture_tags: lecture_tags)
- @announcements = @lecture.announcements.includes(:announcer).order(:created_at).reverse
- @terms = Term.select_terms
- end
+ def eager_load_stuff
+ @lecture = Lecture.includes(:teacher, :term, :editors,
+ :announcements, :imported_media,
+ course: [:editors],
+ media: [:teachable, :tags],
+ lessons: [media: [:tags]],
+ chapters: [:lecture,
+ sections: [lessons: [:tags],
+ chapter: [:lecture],
+ tags: [:notions,
+ :lessons]]])
+ .find_by_id(params[:id])
+ @media = @lecture.media_with_inheritance_uncached_eagerload_stuff
+ lecture_tags = @lecture.tags
+ @course_tags = @lecture.course_tags(lecture_tags: lecture_tags)
+ @extra_tags = @lecture.extra_tags(lecture_tags: lecture_tags)
+ @deferred_tags = @lecture.deferred_tags(lecture_tags: lecture_tags)
+ @announcements = @lecture.announcements.includes(:announcer).order(:created_at).reverse
+ @terms = Term.select_terms
+ end
- def set_erdbeere_data
- @structure_ids = @lecture.structure_ids
- response = Faraday.get(ENV['ERDBEERE_API'] + '/structures')
- response_hash = if response.status == 200
- JSON.parse(response.body)
- else
- { 'data' => {}, 'included' => {} }
- end
- @all_structures = response_hash['data']
- @structures = @all_structures.select do |s|
- s['id'].to_i.in?(@structure_ids)
+ def set_erdbeere_data
+ @structure_ids = @lecture.structure_ids
+ response = Faraday.get(ENV['ERDBEERE_API'] + '/structures')
+ response_hash = if response.status == 200
+ JSON.parse(response.body)
+ else
+ { 'data' => {}, 'included' => {} }
+ end
+ @all_structures = response_hash['data']
+ @structures = @all_structures.select do |s|
+ s['id'].to_i.in?(@structure_ids)
+ end
+ @properties = response_hash['included']
end
- @properties = response_hash['included']
- end
- def search_params
- types = params[:search][:types]
- types = [types] if types && !types.kind_of?(Array)
- types -= [''] if types
- types = nil if types == []
- params[:search][:types] = types
- params[:search][:user_id] = current_user.id
- params.require(:search).permit(:all_types, :all_terms, :all_programs,
- :all_teachers, :fulltext, :per, :user_id,
- :results_as_list,
- types: [],
- term_ids: [],
- program_ids: [],
- teacher_ids: [])
- end
+ def search_params
+ types = params[:search][:types]
+ types = [types] if types && !types.kind_of?(Array)
+ types -= [''] if types
+ types = nil if types == []
+ params[:search][:types] = types
+ params[:search][:user_id] = current_user.id
+ params.require(:search).permit(:all_types, :all_terms, :all_programs,
+ :all_teachers, :fulltext, :per, :user_id,
+ :results_as_list,
+ types: [],
+ term_ids: [],
+ program_ids: [],
+ teacher_ids: [])
+ end
- def check_if_enough_questions
- return if @lecture.course.enough_questions?
- redirect_to :root, alert: I18n.t('controllers.no_test')
- end
+ def check_if_enough_questions
+ return if @lecture.course.enough_questions?
+
+ redirect_to :root, alert: I18n.t('controllers.no_test')
+ end
end
diff --git a/app/controllers/lessons_controller.rb b/app/controllers/lessons_controller.rb
index 546c8a9e9..2425dce7d 100644
--- a/app/controllers/lessons_controller.rb
+++ b/app/controllers/lessons_controller.rb
@@ -46,9 +46,11 @@ def update
@lesson.update(lesson_params)
@errors = @lesson.errors
return unless @errors.blank?
+
update_media_order if params[:lesson][:media_order]
@tags_without_section = @lesson.tags_without_section
return unless @lesson.sections.count == 1 && @tags_without_section.any?
+
section = @lesson.sections.first
section.tags << @tags_without_section
end
@@ -69,28 +71,31 @@ def destroy
private
- def set_lesson
- @lesson = Lesson.find_by_id(params[:id])
- return if @lesson.present?
- redirect_to :root, alert: I18n.t('controllers.no_lesson')
- end
+ def set_lesson
+ @lesson = Lesson.find_by_id(params[:id])
+ return if @lesson.present?
- def lesson_params
- params.require(:lesson).permit(:date, :lecture_id, :start_destination,
- :end_destination, :details,
- section_ids: [],
- tag_ids: [])
- end
+ redirect_to :root, alert: I18n.t('controllers.no_lesson')
+ end
- def update_media_order
- media_order_from_json = JSON.parse(params[:lesson][:media_order])
- return unless media_order_from_json.is_a?(Array)
- media_order = media_order_from_json.map(&:to_i) - [0]
- return unless media_order.sort == @lesson.media.pluck(:id).sort
- Medium.acts_as_list_no_update do
- @lesson.media.each do |m|
- m.update(position: media_order.index(m.id))
+ def lesson_params
+ params.require(:lesson).permit(:date, :lecture_id, :start_destination,
+ :end_destination, :details,
+ section_ids: [],
+ tag_ids: [])
+ end
+
+ def update_media_order
+ media_order_from_json = JSON.parse(params[:lesson][:media_order])
+ return unless media_order_from_json.is_a?(Array)
+
+ media_order = media_order_from_json.map(&:to_i) - [0]
+ return unless media_order.sort == @lesson.media.pluck(:id).sort
+
+ Medium.acts_as_list_no_update do
+ @lesson.media.each do |m|
+ m.update(position: media_order.index(m.id))
+ end
end
end
- end
end
diff --git a/app/controllers/main_controller.rb b/app/controllers/main_controller.rb
index d1769a925..2d8653eae 100644
--- a/app/controllers/main_controller.rb
+++ b/app/controllers/main_controller.rb
@@ -1,6 +1,5 @@
# MainController
class MainController < ApplicationController
-
before_action :check_for_consent
authorize_resource class: false, only: :start
layout 'application_no_sidebar'
@@ -34,7 +33,7 @@ def comments
@media_comments.select! do |m|
(Reader.find_by(user: current_user, thread: m[:thread])
&.updated_at || (Time.now - 1000.years)) < m[:latest_comment].created_at &&
- m[:medium].visible_for_user?(current_user)
+ m[:medium].visible_for_user?(current_user)
end
@media_array = Kaminari.paginate_array(@media_comments)
.page(params[:page]).per(10)
@@ -52,15 +51,16 @@ def start
@talks = current_user.talks.includes(lecture: :term)
.select { |t| t.visible_for_user?(current_user) }
.sort_by do |t|
- [-t.lecture.term.begin_date.jd,
- t.position]
+ [-t.lecture.term.begin_date.jd,
+ t.position]
end
end
private
- def check_for_consent
- return unless user_signed_in?
- redirect_to consent_profile_path unless current_user.consents
- end
+ def check_for_consent
+ return unless user_signed_in?
+
+ redirect_to consent_profile_path unless current_user.consents
+ end
end
diff --git a/app/controllers/media_controller.rb b/app/controllers/media_controller.rb
index a9082d3e6..f3e5678c5 100644
--- a/app/controllers/media_controller.rb
+++ b/app/controllers/media_controller.rb
@@ -65,6 +65,7 @@ def update
@medium.update(medium_params)
@errors = @medium.errors
return unless @errors.empty?
+
# make sure the medium is touched
# (it will not be touched automatically in some cases (e.g. if you only
# update the associated tags), causing trouble for caching)
@@ -93,13 +94,13 @@ def update
# refreshed_video = @medium.video
# @medium.update(video_data: refreshed_video.to_json)
end
- if @medium.sort == 'Quiz' &¶ms[:medium][:create_quiz_graph] == '1'
+ if @medium.sort == 'Quiz' && params[:medium][:create_quiz_graph] == '1'
@medium.becomes(Quiz).update(level: 1,
quiz_graph: QuizGraph.new(vertices: {},
- edges: {},
- root: 0,
- default_table: {},
- hide_solution: []))
+ edges: {},
+ root: 0,
+ default_table: {},
+ hide_solution: []))
end
# if changes to the manuscript have been made,
# remove items that correspond to named destinations that no longer
@@ -123,6 +124,7 @@ def update
end
@tags_without_section = []
return unless @medium.teachable.class.to_s == 'Lesson'
+
add_tags_in_lesson_and_sections
end
@@ -154,11 +156,11 @@ def create
end
if @medium.sort == 'Quiz'
@medium.update(type: 'Quiz')
- @medium.update(quiz_graph:QuizGraph.new(vertices: {},
- edges: {},
- root: 0,
- default_table: {},
- hide_solution: []),
+ @medium.update(quiz_graph: QuizGraph.new(vertices: {},
+ edges: {},
+ root: 0,
+ default_table: {},
+ hide_solution: []),
level: 1)
end
redirect_to edit_medium_path(@medium)
@@ -172,6 +174,7 @@ def publish
publisher = MediumPublisher.parse(@medium, current_user, publish_params)
@errors = publisher.errors
return if @errors.present?
+
@medium.update(publisher: publisher)
if publisher.release_now
@medium.publish!
@@ -217,14 +220,15 @@ def search
filter_media = true
params["search"]["access"] = 'irrelevant'
end
- params["search"]["answers_count"] = 'irrelevant' if search_params[:answers_count].blank?
+ params["search"]["answers_count"] =
+ 'irrelevant' if search_params[:answers_count].blank?
search = Medium.search_by(search_params, params[:page])
search.execute
results = search.results
@total = search.total
- # in the case of a search with tag_operator 'or', we
+ # in the case of a search with tag_operator 'or', we
# execute two searches and merge the results, where media
# with the selected tags are now shown at the front of the list
if search_params[:tag_operator] == "or" and search_params[:all_tags] == "0" and search_params[:fulltext].size >= 2
@@ -304,7 +308,7 @@ def add_item
@item = Item.new(medium: @medium,
start_time: TimeStamp.new(total_seconds: @time))
if @medium.sort == 'Kaviar' &&
- @medium.teachable_type.in?(['Lesson', 'Lecture'])
+ @medium.teachable_type.in?(['Lesson', 'Lecture'])
@item.section = @medium.teachable&.sections&.first
end
end
@@ -341,6 +345,7 @@ def add_screenshot
# remove the video's screenshot
def remove_screenshot
return if @medium.screenshot.nil?
+
@medium.update(screenshot: nil)
end
@@ -376,7 +381,7 @@ def fill_teachable_select
result = (Course.editable_selection(current_user) +
Lecture.editable_selection(current_user) +
Lesson.editable_selection(current_user))
- .map { |t| { value: t[1], text: t[0] } }
+ .map { |t| { value: t[1], text: t[0] } }
render json: result
end
@@ -402,22 +407,36 @@ def get_statistics
medium_consumption = Consumption.where(medium_id: @medium.id)
if @medium.video.present?
@video_downloads = medium_consumption.where(sort: 'video',
- mode: 'download').pluck(:created_at).map(&:to_date).tally.map{|k,t| {x: k,y:t}}.to_json
+ mode: 'download').pluck(:created_at).map(&:to_date).tally.map { |k, t|
+ {
+ x: k, y: t
+ }
+ }.to_json
@video_downloads_count = medium_consumption.where(sort: 'video',
- mode: 'download').count
+ mode: 'download').count
@video_thyme = medium_consumption.where(sort: 'video',
- mode: 'thyme').pluck(:created_at).map(&:to_date).tally.map{|k,t| {x: k,y:t}}.to_json
+ mode: 'thyme').pluck(:created_at).map(&:to_date).tally.map { |k, t|
+ {
+ x: k, y: t
+ }
+ }.to_json
@video_thyme_count = medium_consumption.where(sort: 'video',
mode: 'thyme').count
end
if @medium.manuscript.present?
- @manuscript_access = medium_consumption.where(sort: 'manuscript').pluck(:created_at).map(&:to_date).tally.map{|k,t| {x: k,y:t}}.to_json
+ @manuscript_access = medium_consumption.where(sort: 'manuscript').pluck(:created_at).map(&:to_date).tally.map { |k, t|
+ { x: k, y: t }
+ }.to_json
@manuscript_access_count = medium_consumption.where(sort: 'manuscript').count
end
if @medium.sort == 'Quiz'
- @quiz_plays = medium_consumption.where(sort: 'quiz', mode: 'browser').pluck(:created_at).map(&:to_date).tally.map{|k,t| {x: k,y:t}}.to_json
- @quiz_plays_count = medium_consumption.where(sort: 'quiz', mode: 'browser').count
+ @quiz_plays = medium_consumption.where(sort: 'quiz',
+ mode: 'browser').pluck(:created_at).map(&:to_date).tally.map { |k, t|
+ { x: k, y: t }
+ }.to_json
+ @quiz_plays_count = medium_consumption.where(sort: 'quiz',
+ mode: 'browser').count
@quiz_finished_count = Probe.finished_quizzes(@medium)
@global_success = Probe.global_success_in_quiz(@medium.becomes(Quiz))
@global_success_details = Probe.global_success_details(@medium.becomes(Quiz))
@@ -498,201 +517,205 @@ def fill_reassign_modal
private
- def medium_params
- params.require(:medium).permit(:sort, :description, :video, :manuscript,
- :external_reference_link,
- :external_link_description,
- :geogebra, :geogebra_app_name,
- :teachable_type, :teachable_id,
- :released, :text, :locale,
- :content, :boost,
- editor_ids: [],
- tag_ids: [],
- linked_medium_ids: [])
- end
-
- def publish_params
- params.require(:medium).permit(:release_now, :released, :release_date,
- :lock_comments, :publish_vertices,
- :create_assignment, :assignment_title,
- :assignment_deadline, :assignment_file_type,
- :assignment_deletion_date)
- end
-
- def set_medium
- @medium = Medium.find_by_id(params[:id])&.becomes(Medium)
- return if @medium.present? && @medium.sort != 'RandomQuiz'
- redirect_to :root, alert: I18n.t('controllers.no_medium')
- end
-
- def set_lecture
- @lecture = Lecture.find_by_id(params[:id])
- # store current lecture in cookie
- if @lecture
- cookies[:current_lecture_id] = @lecture.id
- return
+ def medium_params
+ params.require(:medium).permit(:sort, :description, :video, :manuscript,
+ :external_reference_link,
+ :external_link_description,
+ :geogebra, :geogebra_app_name,
+ :teachable_type, :teachable_id,
+ :released, :text, :locale,
+ :content, :boost,
+ editor_ids: [],
+ tag_ids: [],
+ linked_medium_ids: [])
+ end
+
+ def publish_params
+ params.require(:medium).permit(:release_now, :released, :release_date,
+ :lock_comments, :publish_vertices,
+ :create_assignment, :assignment_title,
+ :assignment_deadline, :assignment_file_type,
+ :assignment_deletion_date)
+ end
+
+ def set_medium
+ @medium = Medium.find_by_id(params[:id])&.becomes(Medium)
+ return if @medium.present? && @medium.sort != 'RandomQuiz'
+
+ redirect_to :root, alert: I18n.t('controllers.no_medium')
+ end
+
+ def set_lecture
+ @lecture = Lecture.find_by_id(params[:id])
+ # store current lecture in cookie
+ if @lecture
+ cookies[:current_lecture_id] = @lecture.id
+ return
+ end
+ redirect_to :root, alert: I18n.t('controllers.no_lecture')
+ end
+
+ def set_teachable
+ if params[:teachable_type].in?(['Course', 'Lecture', 'Lesson', 'Talk']) &&
+ params[:teachable_id].present?
+ @teachable = params[:teachable_type].constantize
+ .find_by_id(params[:teachable_id])
+ end
+ end
+
+ def detach_components
+ if params[:medium][:detach_video] == 'true'
+ @medium.update(video: nil)
+ @medium.update(screenshot: nil)
+ end
+ if params[:medium][:detach_geogebra] == 'true' || @medium.sort != 'Sesam'
+ @medium.update(geogebra: nil)
+ end
+ return unless params[:medium][:detach_manuscript] == 'true'
+
+ @medium.update(manuscript: nil)
+ end
+
+ def sanitize_params
+ reveal_contradictions
+ sanitize_page!
+ sanitize_per!
+ params[:all] = (params[:all] == 'true') || (cookies[:all] == 'true')
+ cookies[:all] = params[:all]
+ cookies[:per] = false if cookies[:all]
+ params[:reverse] = params[:reverse] == 'true'
+ end
+
+ def check_for_consent
+ redirect_to consent_profile_path unless current_user.consents
end
- redirect_to :root, alert: I18n.t('controllers.no_lecture')
- end
-
- def set_teachable
- if params[:teachable_type].in?(['Course', 'Lecture', 'Lesson', 'Talk']) &&
- params[:teachable_id].present?
- @teachable = params[:teachable_type].constantize
- .find_by_id(params[:teachable_id])
- end
- end
-
- def detach_components
- if params[:medium][:detach_video] == 'true'
- @medium.update(video: nil)
- @medium.update(screenshot: nil)
- end
- if params[:medium][:detach_geogebra] == 'true' || @medium.sort != 'Sesam'
- @medium.update(geogebra: nil)
- end
- return unless params[:medium][:detach_manuscript] == 'true'
- @medium.update(manuscript: nil)
- end
-
- def sanitize_params
- reveal_contradictions
- sanitize_page!
- sanitize_per!
- params[:all] = (params[:all] == 'true') || (cookies[:all] == 'true')
- cookies[:all] = params[:all]
- cookies[:per] = false if cookies[:all]
- params[:reverse] = params[:reverse] == 'true'
- end
-
- def check_for_consent
- redirect_to consent_profile_path unless current_user.consents
- end
-
- # paginate results obtained by the search_results method
- def paginated_results
- if params[:all]
- total_count = search_results.count
- # without the total count parameter, kaminary will consider only only the
- # first 25 entries
- return Kaminari.paginate_array(search_results,
- total_count: total_count + 1)
- end
- Kaminari.paginate_array(search_results).page(params[:page])
- .per(params[:per])
- end
-
- # search is done in search class method for Medium
- def search_results
- search_results = Medium.search_all(params)
- # search_results are ordered in a certain way
- # the next lines ensure that filtering for visible media does not
- # mess up the ordering
- search_arel = Medium.where(id: search_results.pluck(:id))
- visible_search_results = current_user.filter_visible_media(search_arel)
- search_results &= visible_search_results
- total = search_results.size
- @lecture = Lecture.find_by_id(params[:id])
- # filter out stuff from course level for generic users
- if params[:visibility] == 'lecture'
- search_results.reject! { |m| m.teachable_type == 'Course' }
- # yields only lecture media and course media
- elsif params[:visibility] == 'all'
- # yields all lecture media and course media
- else
- # this is the default setting: 'thematic' selection of media
- # yields all lecture media and course media whose tags have
- # already been dealt with in the lecture
- unless current_user.admin || @lecture.edited_by?(current_user)
- lecture_tags = @lecture.tags_including_media_tags
- search_results.reject! do |m|
- m.teachable_type == 'Course' && (m.tags & lecture_tags).blank?
+
+ # paginate results obtained by the search_results method
+ def paginated_results
+ if params[:all]
+ total_count = search_results.count
+ # without the total count parameter, kaminary will consider only only the
+ # first 25 entries
+ return Kaminari.paginate_array(search_results,
+ total_count: total_count + 1)
+ end
+ Kaminari.paginate_array(search_results).page(params[:page])
+ .per(params[:per])
+ end
+
+ # search is done in search class method for Medium
+ def search_results
+ search_results = Medium.search_all(params)
+ # search_results are ordered in a certain way
+ # the next lines ensure that filtering for visible media does not
+ # mess up the ordering
+ search_arel = Medium.where(id: search_results.pluck(:id))
+ visible_search_results = current_user.filter_visible_media(search_arel)
+ search_results &= visible_search_results
+ total = search_results.size
+ @lecture = Lecture.find_by_id(params[:id])
+ # filter out stuff from course level for generic users
+ if params[:visibility] == 'lecture'
+ search_results.reject! { |m| m.teachable_type == 'Course' }
+ # yields only lecture media and course media
+ elsif params[:visibility] == 'all'
+ # yields all lecture media and course media
+ else
+ # this is the default setting: 'thematic' selection of media
+ # yields all lecture media and course media whose tags have
+ # already been dealt with in the lecture
+ unless current_user.admin || @lecture.edited_by?(current_user)
+ lecture_tags = @lecture.tags_including_media_tags
+ search_results.reject! do |m|
+ m.teachable_type == 'Course' && (m.tags & lecture_tags).blank?
+ end
end
end
+ sort = params[:project] == 'keks' ? 'Quiz' : params[:project]&.capitalize
+ search_results += @lecture.imported_media
+ .where(sort: sort)
+ .locally_visible
+ search_results.uniq!
+ @hidden = search_results.empty? && total.positive?
+ return search_results unless params[:reverse]
+
+ search_results.reverse
end
- sort = params[:project] == 'keks' ? 'Quiz' : params[:project]&.capitalize
- search_results += @lecture.imported_media
- .where(sort: sort)
- .locally_visible
- search_results.uniq!
- @hidden = search_results.empty? && total.positive?
- return search_results unless params[:reverse]
- search_results.reverse
- end
-
- def reveal_contradictions
- return unless params[:lecture_id].present?
- return if params[:lecture_id].to_i.in?(@course.lecture_ids)
- redirect_to :root, alert: I18n.t('controllers.contradiction')
- end
-
- def sanitize_page!
- params[:page] = params[:page].to_i.positive? ? params[:page].to_i : 1
- end
-
- def sanitize_per!
- if params[:per] || cookies[:per].to_i.positive?
- cookies[:all] = 'false'
- end
- params[:per] = if params[:per].to_i.in?([3, 4, 8, 12, 24, 48])
- params[:per].to_i
- elsif cookies[:per].to_i.positive?
- cookies[:per].to_i
- else
- 8
- end
- cookies[:per] = params[:per]
- end
-
- def search_params
- types = params[:search][:types] || []
- types = [types] if types && !types.kind_of?(Array)
- types -= [''] if types
- types = nil if types == []
- params[:search][:types] = types
- params[:search][:user_id] = current_user.id
- params.require(:search)
- .permit(:all_types, :all_teachables, :all_tags,
- :all_editors, :tag_operator, :quiz, :access,
- :teachable_inheritance, :fulltext, :per,
- :clicker, :purpose, :answers_count,
- :results_as_list, :all_terms, :all_teachers,
- :lecture_option, :user_id,
- types: [],
- teachable_ids: [],
- tag_ids: [],
- editor_ids: [],
- term_ids: [],
- teacher_ids: [],
- media_lectures: [])
- #.with_defaults(access: 'all')
- end
-
- # destroy all notifications related to this medium
- def destroy_notifications
- Notification.where(notifiable_id: @medium.id, notifiable_type: 'Medium')
- .delete_all
- end
-
- def add_tags_in_lesson_and_sections
- @tags_outside_lesson = @medium.tags_outside_lesson
- if @tags_outside_lesson
- @medium.teachable.tags << @tags_outside_lesson
- @tags_without_section = @tags_outside_lesson & @medium.teachable.tags_without_section
- if @medium.teachable.sections.count == 1
- section = @medium.teachable.sections.first
- section.tags << @tags_without_section
+
+ def reveal_contradictions
+ return unless params[:lecture_id].present?
+ return if params[:lecture_id].to_i.in?(@course.lecture_ids)
+
+ redirect_to :root, alert: I18n.t('controllers.contradiction')
+ end
+
+ def sanitize_page!
+ params[:page] = params[:page].to_i.positive? ? params[:page].to_i : 1
+ end
+
+ def sanitize_per!
+ if params[:per] || cookies[:per].to_i.positive?
+ cookies[:all] = 'false'
end
+ params[:per] = if params[:per].to_i.in?([3, 4, 8, 12, 24, 48])
+ params[:per].to_i
+ elsif cookies[:per].to_i.positive?
+ cookies[:per].to_i
+ else
+ 8
+ end
+ cookies[:per] = params[:per]
+ end
+
+ def search_params
+ types = params[:search][:types] || []
+ types = [types] if types && !types.kind_of?(Array)
+ types -= [''] if types
+ types = nil if types == []
+ params[:search][:types] = types
+ params[:search][:user_id] = current_user.id
+ params.require(:search)
+ .permit(:all_types, :all_teachables, :all_tags,
+ :all_editors, :tag_operator, :quiz, :access,
+ :teachable_inheritance, :fulltext, :per,
+ :clicker, :purpose, :answers_count,
+ :results_as_list, :all_terms, :all_teachers,
+ :lecture_option, :user_id,
+ types: [],
+ teachable_ids: [],
+ tag_ids: [],
+ editor_ids: [],
+ term_ids: [],
+ teacher_ids: [],
+ media_lectures: [])
+ # .with_defaults(access: 'all')
end
- end
- def store_access
- mode = action_name == 'play' ? 'thyme' : 'pdf_view'
- sort = action_name == 'play' ? 'video' : 'manuscript'
- ConsumptionSaver.perform_async(@medium.id, mode, sort)
- end
+ # destroy all notifications related to this medium
+ def destroy_notifications
+ Notification.where(notifiable_id: @medium.id, notifiable_type: 'Medium')
+ .delete_all
+ end
+
+ def add_tags_in_lesson_and_sections
+ @tags_outside_lesson = @medium.tags_outside_lesson
+ if @tags_outside_lesson
+ @medium.teachable.tags << @tags_outside_lesson
+ @tags_without_section = @tags_outside_lesson & @medium.teachable.tags_without_section
+ if @medium.teachable.sections.count == 1
+ section = @medium.teachable.sections.first
+ section.tags << @tags_without_section
+ end
+ end
+ end
- def store_download
- ConsumptionSaver.perform_async(@medium.id, 'download', params[:sort])
- end
+ def store_access
+ mode = action_name == 'play' ? 'thyme' : 'pdf_view'
+ sort = action_name == 'play' ? 'video' : 'manuscript'
+ ConsumptionSaver.perform_async(@medium.id, mode, sort)
+ end
+
+ def store_download
+ ConsumptionSaver.perform_async(@medium.id, 'download', params[:sort])
+ end
end
diff --git a/app/controllers/notifications_controller.rb b/app/controllers/notifications_controller.rb
index b65fda5dc..a43809799 100644
--- a/app/controllers/notifications_controller.rb
+++ b/app/controllers/notifications_controller.rb
@@ -29,6 +29,7 @@ def destroy_all
def destroy_lecture_notifications
lecture = Lecture.find_by_id(params[:lecture_id])
return unless lecture.present?
+
Notification.delete(current_user.active_notifications(lecture).pluck(:id))
current_user.touch
render :destroy_all
@@ -44,9 +45,10 @@ def destroy_news_notifications
private
- def set_notification
- @notification = Notification.find_by_id(params[:id])
- return if @notification.present?
- redirect_to :root, alert: I18n.t('controllers.no_notification')
- end
+ def set_notification
+ @notification = Notification.find_by_id(params[:id])
+ return if @notification.present?
+
+ redirect_to :root, alert: I18n.t('controllers.no_notification')
+ end
end
diff --git a/app/controllers/profile_controller.rb b/app/controllers/profile_controller.rb
index 978a90447..d74eeb08a 100644
--- a/app/controllers/profile_controller.rb
+++ b/app/controllers/profile_controller.rb
@@ -24,6 +24,7 @@ def edit
def update
check_passphrases
return if @errors.present?
+
if @user.update(lectures: @lectures,
name: @name,
name_in_tutorials: @name_in_tutorials,
@@ -51,6 +52,7 @@ def check_for_consent
return
end
return unless @user.consents
+
redirect_to edit_profile_path,
notice: t('profile.please_update')
end
@@ -69,20 +71,21 @@ def toggle_thread_subscription
else
@thread.unsubscribe(@user)
end
- @result = !!@thread.subscription_for(@user)
+ @result = !!@thread.subscription_for(@user)
end
end
def subscribe_lecture
@success = false
if !@lecture.published? && !current_user.admin &&
- !@lecture.edited_by?(current_user)
+ !@lecture.edited_by?(current_user)
@unpublished = true
return
end
return if @lecture.passphrase.present? &&
- !@lecture.in?(current_user.lectures) &&
- @lecture.passphrase != @passphrase
+ !@lecture.in?(current_user.lectures) &&
+ @lecture.passphrase != @passphrase
+
@success = current_user.subscribe_lecture!(@lecture)
redirect_to lecture_path(@lecture) if @parent == "redirect"
@@ -91,14 +94,15 @@ def subscribe_lecture
def unsubscribe_lecture
@success = current_user.unsubscribe_lecture!(@lecture)
@none_left = case @parent
- when 'current_subscribed' then current_user.current_subscribed_lectures
- .empty?
- when 'inactive' then current_user.inactive_lectures.empty?
+ when 'current_subscribed' then current_user.current_subscribed_lectures
+ .empty?
+ when 'inactive' then current_user.inactive_lectures.empty?
end
end
def star_lecture
return unless @lecture&.in?(current_user.lectures)
+
if !@lecture.in?(current_user.favorite_lectures)
current_user.favorite_lectures << @lecture
end
@@ -111,6 +115,7 @@ def star_lecture
def unstar_lecture
return unless @lecture
+
current_user.favorite_lectures.delete(@lecture)
current_user.touch
end
@@ -118,12 +123,13 @@ def unstar_lecture
def show_accordion
@collapse_id = params[:id]
redirect_to :root and return unless @collapse_id.present?
+
@lectures = case @collapse_id
- when 'collapseCurrentStuff' then current_user.current_subscribed_lectures
- when 'collapseInactiveLectures' then current_user.inactive_lectures
- .includes(:course, :term)
- .sort
- when 'collapseAllCurrent' then current_user.current_subscribable_lectures
+ when 'collapseCurrentStuff' then current_user.current_subscribed_lectures
+ when 'collapseInactiveLectures' then current_user.inactive_lectures
+ .includes(:course, :term)
+ .sort
+ when 'collapseAllCurrent' then current_user.current_subscribable_lectures
end
@link = @collapse_id.remove('collapse').camelize(:lower) + 'Link'
end
@@ -136,81 +142,81 @@ def request_data
private
- def set_user
- @user = current_user
- end
+ def set_user
+ @user = current_user
+ end
- def set_basics
- @subscription_type = params[:user][:subscription_type].to_i
- @name = params[:user][:name]
- @name_in_tutorials = params[:user][:name_in_tutorials]
- @lectures = Lecture.where(id: lecture_ids)
- @courses = Course.where(id: @lectures.pluck(:course_id).uniq)
- @locale = params[:user][:locale]
- end
+ def set_basics
+ @subscription_type = params[:user][:subscription_type].to_i
+ @name = params[:user][:name]
+ @name_in_tutorials = params[:user][:name_in_tutorials]
+ @lectures = Lecture.where(id: lecture_ids)
+ @courses = Course.where(id: @lectures.pluck(:course_id).uniq)
+ @locale = params[:user][:locale]
+ end
- def email_params
- params.require(:user).permit(:email_for_medium, :email_for_announcement,
- :email_for_teachable, :email_for_news,
- :email_for_submission_upload,
- :email_for_submission_removal,
- :email_for_submission_join,
- :email_for_submission_leave,
- :email_for_correction_upload,
- :email_for_submission_decision)
- end
+ def email_params
+ params.require(:user).permit(:email_for_medium, :email_for_announcement,
+ :email_for_teachable, :email_for_news,
+ :email_for_submission_upload,
+ :email_for_submission_removal,
+ :email_for_submission_join,
+ :email_for_submission_leave,
+ :email_for_correction_upload,
+ :email_for_submission_decision)
+ end
- def set_lecture
- @lecture = Lecture.find_by_id(lecture_params[:id])
- @passphrase = lecture_params[:passphrase]
- @parent = lecture_params[:parent]
- @current = !@parent.in?(['lectureSearch', 'inactive'])
- redirect_to start_path unless @lecture
- end
+ def set_lecture
+ @lecture = Lecture.find_by_id(lecture_params[:id])
+ @passphrase = lecture_params[:passphrase]
+ @parent = lecture_params[:parent]
+ @current = !@parent.in?(['lectureSearch', 'inactive'])
+ redirect_to start_path unless @lecture
+ end
- def lecture_params
- params.require(:lecture).permit(:id, :passphrase, :parent)
- end
+ def lecture_params
+ params.require(:lecture).permit(:id, :passphrase, :parent)
+ end
- # extracts all lecture ids from user params
- def lecture_ids
- params[:user][:lecture].select { |k, v| v == '1' }.keys.map(&:to_i)
- end
+ # extracts all lecture ids from user params
+ def lecture_ids
+ params[:user][:lecture].select { |k, v| v == '1' }.keys.map(&:to_i)
+ end
- def clean_up_notifications
- # delete all of the user's notifications if he does not want them
- # remove all notification related not related to subscribed courses
- # or lectures
- subscribed_teachables = @courses + @lectures
- irrelevant_notifications = @user.notifications.select do |n|
- n.teachable.present? && !n.teachable.in?(subscribed_teachables)
+ def clean_up_notifications
+ # delete all of the user's notifications if he does not want them
+ # remove all notification related not related to subscribed courses
+ # or lectures
+ subscribed_teachables = @courses + @lectures
+ irrelevant_notifications = @user.notifications.select do |n|
+ n.teachable.present? && !n.teachable.in?(subscribed_teachables)
+ end
+ Notification.where(id: irrelevant_notifications.map(&:id)).delete_all
end
- Notification.where(id: irrelevant_notifications.map(&:id)).delete_all
- end
- # if user unsubscribed the lecture the current lecture cookie refers to,
- # set the lectures cookie to nil
- def update_lecture_cookie
- unless @current_lecture.in?(@user.lectures)
- cookies[:current_lecture_id] = nil
+ # if user unsubscribed the lecture the current lecture cookie refers to,
+ # set the lectures cookie to nil
+ def update_lecture_cookie
+ unless @current_lecture.in?(@user.lectures)
+ cookies[:current_lecture_id] = nil
+ end
end
- end
- # stop the update if any of passphrases for newly subscribed
- # lectures is incorrect
- def check_passphrases
- @errors = {}
- restricted_lectures = Lecture.where(id: lecture_ids)
- .select do |l|
- l.in?(l.course
- .to_be_authorized_lectures(current_user))
- end
- restricted_lectures.each do |l|
- given_passphrase = params[:user][:pass_lecture][l.id.to_s]
- unless given_passphrase == l.passphrase
- @errors[:passphrase] ||= []
- @errors[:passphrase].push l.id
+ # stop the update if any of passphrases for newly subscribed
+ # lectures is incorrect
+ def check_passphrases
+ @errors = {}
+ restricted_lectures = Lecture.where(id: lecture_ids)
+ .select do |l|
+ l.in?(l.course
+ .to_be_authorized_lectures(current_user))
+ end
+ restricted_lectures.each do |l|
+ given_passphrase = params[:user][:pass_lecture][l.id.to_s]
+ unless given_passphrase == l.passphrase
+ @errors[:passphrase] ||= []
+ @errors[:passphrase].push l.id
+ end
end
end
- end
end
diff --git a/app/controllers/programs_controller.rb b/app/controllers/programs_controller.rb
index 096e082fb..babb0eb30 100644
--- a/app/controllers/programs_controller.rb
+++ b/app/controllers/programs_controller.rb
@@ -3,47 +3,46 @@ class ProgramsController < ApplicationController
before_action :set_program, except: [:new, :create]
authorize_resource except: [:new, :create]
-
def current_ability
@current_ability ||= ProgramAbility.new(current_user)
end
- def edit
- end
+ def edit
+ end
- def new
- @program = Program.new(subject_id: params[:subject_id].to_i)
+ def new
+ @program = Program.new(subject_id: params[:subject_id].to_i)
authorize! :new, @program
- end
+ end
- def update
- @program.update(program_params)
- redirect_to classification_path
- end
+ def update
+ @program.update(program_params)
+ redirect_to classification_path
+ end
- def create
- @program = Program.new(program_params)
- @program.subject_id = params[:program][:subject_id].to_i
+ def create
+ @program = Program.new(program_params)
+ @program.subject_id = params[:program][:subject_id].to_i
authorize! :create, @program
- @program.save
- redirect_to classification_path
- end
+ @program.save
+ redirect_to classification_path
+ end
- def destroy
- @program.destroy
- redirect_to classification_path
- end
+ def destroy
+ @program.destroy
+ redirect_to classification_path
+ end
private
- def set_program
- @program = Program.find_by_id(params[:id])
- return if @program.present?
+ def set_program
+ @program = Program.find_by_id(params[:id])
+ return if @program.present?
- redirect_to root_path, alert: I18n.t('controllers.no_program')
- end
+ redirect_to root_path, alert: I18n.t('controllers.no_program')
+ end
- def program_params
- params.require(:program).permit(*Program.globalize_attribute_names)
- end
-end
\ No newline at end of file
+ def program_params
+ params.require(:program).permit(*Program.globalize_attribute_names)
+ end
+end
diff --git a/app/controllers/questions_controller.rb b/app/controllers/questions_controller.rb
index 7daaf3936..1444e3ba1 100644
--- a/app/controllers/questions_controller.rb
+++ b/app/controllers/questions_controller.rb
@@ -16,6 +16,7 @@ def edit
def update
return if @errors
+
@success = true if @question.update(question_params)
if question_params[:question_sort] == 'free'
answer = @question.answers.first
@@ -53,14 +54,14 @@ def reassign
def set_solution_type
content = if params[:type] == 'MampfExpression'
- MampfExpression.trivial_instance
- elsif params[:type] == 'MampfMatrix'
- MampfMatrix.trivial_instance
- elsif params[:type] == 'MampfTuple'
- MampfTuple.trivial_instance
- elsif params[:type] == 'MampfSet'
- MampfSet.trivial_instance
- end
+ MampfExpression.trivial_instance
+ elsif params[:type] == 'MampfMatrix'
+ MampfMatrix.trivial_instance
+ elsif params[:type] == 'MampfTuple'
+ MampfTuple.trivial_instance
+ elsif params[:type] == 'MampfSet'
+ MampfSet.trivial_instance
+ end
@solution = Solution.new(content)
end
@@ -76,33 +77,37 @@ def render_question_parameters
private
- def set_question
- @question = Question.find_by_id(params[:id])
- return if @question.present?
- redirect_to :root, alert: I18n.t('controllers.no_question')
- end
+ def set_question
+ @question = Question.find_by_id(params[:id])
+ return if @question.present?
- def set_quizzes
- @quizzes = params[:question].select { |k, v| v == '1' && k.start_with?('quiz-') }
- .keys.map { |k| k.remove('quiz-').to_i }
- end
+ redirect_to :root, alert: I18n.t('controllers.no_question')
+ end
- def check_solution_errors
- return unless params[:question][:solution_error].present?
- @errors = ActiveModel::Errors.new(@question)
- @errors.add(:base, params[:question][:solution_error])
- end
+ def set_quizzes
+ @quizzes = params[:question].select { |k, v|
+ v == '1' && k.start_with?('quiz-')
+ }
+ .keys.map { |k| k.remove('quiz-').to_i }
+ end
+
+ def check_solution_errors
+ return unless params[:question][:solution_error].present?
- def question_params
- result = params.require(:question)
- .permit(:label, :text, :type, :hint, :level,
- :question_sort, :independent, :vertex_id,
- :solution_type,
- solution_content: {})
- if result[:solution_type] && result[:solution_content]
- result[:solution] = Solution.from_hash(result[:solution_type],
- result[:solution_content])
+ @errors = ActiveModel::Errors.new(@question)
+ @errors.add(:base, params[:question][:solution_error])
+ end
+
+ def question_params
+ result = params.require(:question)
+ .permit(:label, :text, :type, :hint, :level,
+ :question_sort, :independent, :vertex_id,
+ :solution_type,
+ solution_content: {})
+ if result[:solution_type] && result[:solution_content]
+ result[:solution] = Solution.from_hash(result[:solution_type],
+ result[:solution_content])
+ end
+ result.except(:solution_type, :solution_content)
end
- result.except(:solution_type, :solution_content)
- end
end
diff --git a/app/controllers/quiz_certificates_controller.rb b/app/controllers/quiz_certificates_controller.rb
index 572dca0a8..0f611e18d 100644
--- a/app/controllers/quiz_certificates_controller.rb
+++ b/app/controllers/quiz_certificates_controller.rb
@@ -22,31 +22,35 @@ def validate
private
- def set_certificate
- @certificate = QuizCertificate.find_by_id(params[:id])
- return if @certificate.present?
- redirect_to :root, alert: I18n.t('controllers.no_certificate')
- end
+ def set_certificate
+ @certificate = QuizCertificate.find_by_id(params[:id])
+ return if @certificate.present?
- def check_if_claimed
- return unless @certificate.user
- redirect_to :root, alert: I18n.t('controllers.certificate_already_claimed')
- end
+ redirect_to :root, alert: I18n.t('controllers.no_certificate')
+ end
- def certificate_params
- params.permit(:code, :lecture_id)
- end
+ def check_if_claimed
+ return unless @certificate.user
+
+ redirect_to :root,
+ alert: I18n.t('controllers.certificate_already_claimed')
+ end
- def set_locale_by_quiz
- return unless @certificate
- quiz_locale = @certificate.quiz.locale_with_inheritance
- I18n.locale = quiz_locale || current_user.locale ||
+ def certificate_params
+ params.permit(:code, :lecture_id)
+ end
+
+ def set_locale_by_quiz
+ return unless @certificate
+
+ quiz_locale = @certificate.quiz.locale_with_inheritance
+ I18n.locale = quiz_locale || current_user.locale ||
I18n.default_locale
- end
+ end
- def set_locale_by_lecture
- @lecture = Lecture.find_by_id(certificate_params[:lecture_id])
- I18n.locale = @lecture&.locale_with_inheritance || current_user.locale ||
+ def set_locale_by_lecture
+ @lecture = Lecture.find_by_id(certificate_params[:lecture_id])
+ I18n.locale = @lecture&.locale_with_inheritance || current_user.locale ||
I18n.default_locale
- end
-end
\ No newline at end of file
+ end
+end
diff --git a/app/controllers/quizzes_controller.rb b/app/controllers/quizzes_controller.rb
index 3e92d5c6c..3cf4ead9c 100644
--- a/app/controllers/quizzes_controller.rb
+++ b/app/controllers/quizzes_controller.rb
@@ -98,64 +98,69 @@ def render_vertex_quizzable
private
- def set_quiz
- @quiz = Quiz.find_by_id(params[:id])
- return if @quiz.present?
- redirect_to :root, alert: I18n.t('controllers.no_quiz')
- end
+ def set_quiz
+ @quiz = Quiz.find_by_id(params[:id])
+ return if @quiz.present?
- def init_values
- quiz_round_params = if params[:question].present? &&
- params[:question][:solution_type].present?
- params[:question]
- else
- params
- end
- if user_signed_in? && current_user.study_participant
- quiz_round_params[:study_participant] = current_user.anonymized_id
+ redirect_to :root, alert: I18n.t('controllers.no_quiz')
end
- quiz_round_params[:save_probe] =
- if !user_signed_in?
- true
- elsif current_user.admin?
- false
- elsif current_user.in?(Quiz.find(params[:id]).editors_with_inheritance)
- false
+
+ def init_values
+ quiz_round_params = if params[:question].present? &&
+ params[:question][:solution_type].present?
+ params[:question]
else
- true
+ params
end
- @quiz_round = QuizRound.new(quiz_round_params)
- end
+ if user_signed_in? && current_user.study_participant
+ quiz_round_params[:study_participant] = current_user.anonymized_id
+ end
+ quiz_round_params[:save_probe] =
+ if !user_signed_in?
+ true
+ elsif current_user.admin?
+ false
+ elsif current_user.in?(Quiz.find(params[:id]).editors_with_inheritance)
+ false
+ else
+ true
+ end
+ @quiz_round = QuizRound.new(quiz_round_params)
+ end
- def quiz_params
- params.require(:quiz).permit(:label, :root, :level, :id_js)
- end
+ def quiz_params
+ params.require(:quiz).permit(:label, :root, :level, :id_js)
+ end
- def check_accessibility
- return if @quiz.sort == 'RandomQuiz'
- return if user_signed_in? && @quiz.visible_for_user?(current_user)
- return if !user_signed_in? && @quiz.free?
- redirect_to :root, alert: I18n.t('controllers.no_quiz_access')
- end
+ def check_accessibility
+ return if @quiz.sort == 'RandomQuiz'
+ return if user_signed_in? && @quiz.visible_for_user?(current_user)
+ return if !user_signed_in? && @quiz.free?
- def check_vertex_accessibility
- return if @quiz.sort == 'RandomQuiz'
- if user_signed_in?
- return if current_user.in?(@quiz.editors_with_inheritance)
- return if current_user.admin
- return if @quiz.quizzables_visible_for_user?(current_user)
+ redirect_to :root, alert: I18n.t('controllers.no_quiz_access')
end
- return if !user_signed_in? && @quiz.quizzables_free?
- redirect_to :root, alert: I18n.t('controllers.no_quiz_vertex_access')
- end
- def check_errors
- return if @quiz.sort == 'RandomQuiz'
- return unless @quiz.find_errors&.any?
- redirect_to :root, alert: I18n.t('controllers.quiz_has_error')
- end
+ def check_vertex_accessibility
+ return if @quiz.sort == 'RandomQuiz'
- def store_access
- ConsumptionSaver.perform_async(@quiz.id, 'browser', 'quiz')
- end
+ if user_signed_in?
+ return if current_user.in?(@quiz.editors_with_inheritance)
+ return if current_user.admin
+ return if @quiz.quizzables_visible_for_user?(current_user)
+ end
+ return if !user_signed_in? && @quiz.quizzables_free?
+
+ redirect_to :root, alert: I18n.t('controllers.no_quiz_vertex_access')
+ end
+
+ def check_errors
+ return if @quiz.sort == 'RandomQuiz'
+ return unless @quiz.find_errors&.any?
+
+ redirect_to :root, alert: I18n.t('controllers.quiz_has_error')
+ end
+
+ def store_access
+ ConsumptionSaver.perform_async(@quiz.id, 'browser', 'quiz')
+ end
end
diff --git a/app/controllers/readers_controller.rb b/app/controllers/readers_controller.rb
index 6bd1587ab..362e5cd86 100644
--- a/app/controllers/readers_controller.rb
+++ b/app/controllers/readers_controller.rb
@@ -5,6 +5,7 @@ class ReadersController < ApplicationController
def update
@thread = Commontator::Thread.find_by_id(reader_params[:thread_id])
return unless @thread
+
@reader = Reader.find_or_create_by(user: current_user,
thread: @thread)
@reader.touch
@@ -32,7 +33,7 @@ def update_all
private
- def reader_params
- params.permit(:thread_id)
- end
-end
\ No newline at end of file
+ def reader_params
+ params.permit(:thread_id)
+ end
+end
diff --git a/app/controllers/referrals_controller.rb b/app/controllers/referrals_controller.rb
index c058bf57e..4d07fa221 100644
--- a/app/controllers/referrals_controller.rb
+++ b/app/controllers/referrals_controller.rb
@@ -15,6 +15,7 @@ def update
# be affected; links are changed *globally*
update_item if Item.find_by_id(@item_id)&.sort == 'link'
return if @errors.present?
+
@referral.update(updated_params)
@errors = @referral.errors unless @referral.valid?
end
@@ -25,12 +26,12 @@ def edit
# otherwise load all items in the referral's item's medium scope
# that the user can choose from in the item dropdown menu
@item_selection = if @referral.item.sort == 'link'
- Item.where(medium: nil)
- .map { |i| [i.description, i.id] }
- else
- @referral.item.medium.teachable.media_scope
- .media_items_with_inheritance
- end
+ Item.where(medium: nil)
+ .map { |i| [i.description, i.id] }
+ else
+ @referral.item.medium.teachable.media_scope
+ .media_items_with_inheritance
+ end
@item = Item.new(sort: 'link')
end
@@ -70,36 +71,36 @@ def list_items
private
- def set_referral
- @referral = Referral.find(params[:id])
- end
+ def set_referral
+ @referral = Referral.find(params[:id])
+ end
- def set_basics
- @item_id = params[:referral][:item_id].to_i
- end
+ def set_basics
+ @item_id = params[:referral][:item_id].to_i
+ end
- def referral_params
- # clone referral params in order to convert start and end time to proper
- # TimeStamp instances
- filter = params.require(:referral).permit(:medium_id, :item_id, :start_time,
- :end_time, :description, :link,
- :explanation, :ref_id).clone
- filter[:start_time] = TimeStamp.new(time_string: filter[:start_time])
- filter[:end_time] = TimeStamp.new(time_string: filter[:end_time])
- filter
- end
+ def referral_params
+ # clone referral params in order to convert start and end time to proper
+ # TimeStamp instances
+ filter = params.require(:referral).permit(:medium_id, :item_id, :start_time,
+ :end_time, :description, :link,
+ :explanation, :ref_id).clone
+ filter[:start_time] = TimeStamp.new(time_string: filter[:start_time])
+ filter[:end_time] = TimeStamp.new(time_string: filter[:end_time])
+ filter
+ end
- def update_item
- item = Item.find(@item_id)
- item.update(link: referral_params[:link],
- description: referral_params[:description])
- @errors = item.errors unless item.valid?
- end
+ def update_item
+ item = Item.find(@item_id)
+ item.update(link: referral_params[:link],
+ description: referral_params[:description])
+ @errors = item.errors unless item.valid?
+ end
- def updated_params
- { medium_id: referral_params[:medium_id], item_id: @item_id,
- explanation: referral_params[:explanation],
- start_time: referral_params[:start_time],
- end_time: referral_params[:end_time] }
- end
+ def updated_params
+ { medium_id: referral_params[:medium_id], item_id: @item_id,
+ explanation: referral_params[:explanation],
+ start_time: referral_params[:start_time],
+ end_time: referral_params[:end_time] }
+ end
end
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index ec884e78d..0cd93ae14 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -7,10 +7,11 @@ class RegistrationsController < Devise::RegistrationsController
def verify_captcha
return true unless ENV['USE_CAPTCHA_SERVICE']
+
begin
uri = URI.parse(ENV['CAPTCHA_VERIFY_URL'])
- data = { message:params["frc-captcha-solution"],
- application_token:ENV['CAPTCHA_APPLICATION_TOKEN'] }
+ data = { message: params["frc-captcha-solution"],
+ application_token: ENV['CAPTCHA_APPLICATION_TOKEN'] }
header = { 'Content-Type': 'text/json' }
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true if ENV['CAPTCHA_VERIFY_URL'].include?('https')
@@ -19,7 +20,7 @@ def verify_captcha
# Send the request
response = http.request(request)
- answer = JSON.parse(response.body)
+ answer = JSON.parse(response.body)
return true if answer["message"] == "verified"
rescue
end
@@ -41,19 +42,25 @@ def destroy
password_correct = resource.valid_password?(deletion_params[:password])
if !password_correct
set_flash_message :alert, :password_incorrect
- respond_with_navigational(resource){ redirect_to after_sign_up_path_for(resource_name) }
+ respond_with_navigational(resource) {
+ redirect_to after_sign_up_path_for(resource_name)
+ }
return
end
success = resource.archive_and_destroy(deletion_params[:archive_name])
if !success
set_flash_message :alert, :not_destroyed
- respond_with_navigational(resource){ redirect_to after_sign_up_path_for(resource_name) }
+ respond_with_navigational(resource) {
+ redirect_to after_sign_up_path_for(resource_name)
+ }
return
end
Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name)
set_flash_message :notice, :destroyed
yield resource if block_given?
- respond_with_navigational(resource){ redirect_to after_sign_out_path_for(resource_name) }
+ respond_with_navigational(resource) {
+ redirect_to after_sign_out_path_for(resource_name)
+ }
end
def after_sign_up_path_for(resource)
@@ -62,17 +69,17 @@ def after_sign_up_path_for(resource)
private
- def check_registration_limit
- if User.where("users.confirmed_at is NULL and users.created_at > '#{(DateTime.now()-(ENV['MAMPF_REGISTRATION_TIMEFRAME']||15).to_i.minutes)}'").count > (ENV['MAMPF_MAX_REGISTRATION_PER_TIMEFRAME'] || 40).to_i
- self.resource = resource_class.new devise_parameter_sanitizer.sanitize(:sign_up)
- resource.validate # Look for any other validation errors besides reCAPTCHA
- set_flash_message :alert, :too_many_registrations
- set_minimum_password_length
- respond_with_navigational(resource) { render :new }
+ def check_registration_limit
+ if User.where("users.confirmed_at is NULL and users.created_at > '#{(DateTime.now() - (ENV['MAMPF_REGISTRATION_TIMEFRAME'] || 15).to_i.minutes)}'").count > (ENV['MAMPF_MAX_REGISTRATION_PER_TIMEFRAME'] || 40).to_i
+ self.resource = resource_class.new devise_parameter_sanitizer.sanitize(:sign_up)
+ resource.validate # Look for any other validation errors besides reCAPTCHA
+ set_flash_message :alert, :too_many_registrations
+ set_minimum_password_length
+ respond_with_navigational(resource) { render :new }
+ end
end
- end
- def deletion_params
- params.permit(:archive_name, :password)
- end
+ def deletion_params
+ params.permit(:archive_name, :password)
+ end
end
diff --git a/app/controllers/remarks_controller.rb b/app/controllers/remarks_controller.rb
index c1529482b..9d95e9779 100644
--- a/app/controllers/remarks_controller.rb
+++ b/app/controllers/remarks_controller.rb
@@ -41,18 +41,19 @@ def cancel_remark_basics
private
- def set_remark
- @remark = Remark.find_by_id(params[:id])
- return if @remark.present?
- redirect_to remarks_path, alert: I18n.t('controllers.no_remark')
- end
+ def set_remark
+ @remark = Remark.find_by_id(params[:id])
+ return if @remark.present?
- def set_quizzes
- @quizzes = params[:remark].select { |_k, v| v == '1' }.keys
- .map { |k| k.remove('quiz-').to_i }
- end
+ redirect_to remarks_path, alert: I18n.t('controllers.no_remark')
+ end
- def remark_params
- params.require(:remark).permit(:text, :text_input, :type)
- end
+ def set_quizzes
+ @quizzes = params[:remark].select { |_k, v| v == '1' }.keys
+ .map { |k| k.remove('quiz-').to_i }
+ end
+
+ def remark_params
+ params.require(:remark).permit(:text, :text_input, :type)
+ end
end
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 662b36536..ef9d49636 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -20,35 +20,37 @@ def index
# (taking into account his preferences and subscribed courses)
@filtered_tags = current_user.filter_tags(@tags)
return unless @tags.empty?
+
# determine tags whose title is apartial match
find_similar_tags
end
private
- def check_for_consent
- redirect_to consent_profile_path unless current_user.consents
- end
+ def check_for_consent
+ redirect_to consent_profile_path unless current_user.consents
+ end
- def set_search_string
- @search_string = params[:search]
- end
+ def set_search_string
+ @search_string = params[:search]
+ end
+
+ # make sure the seacrh string is not blank and consists of at least
+ # two letters
+ def sanitize_search_string
+ if @search_string.nil?
+ redirect_back fallback_location: root_path,
+ alert: I18n.t('controllers.no_search_term')
+ return
+ end
+ return if @search_string.length > 1
- # make sure the seacrh string is not blank and consists of at least
- # two letters
- def sanitize_search_string
- if @search_string.nil?
redirect_back fallback_location: root_path,
- alert: I18n.t('controllers.no_search_term')
- return
+ alert: I18n.t('controllers.search_term_short')
end
- return if @search_string.length > 1
- redirect_back fallback_location: root_path,
- alert: I18n.t('controllers.search_term_short')
- end
- def find_similar_tags
- @similar_tags = Tag.similar_tags(@search_string)
- @filtered_similar_tags = current_user.filter_tags(@similar_tags)
- end
+ def find_similar_tags
+ @similar_tags = Tag.similar_tags(@search_string)
+ @filtered_similar_tags = current_user.filter_tags(@similar_tags)
+ end
end
diff --git a/app/controllers/sections_controller.rb b/app/controllers/sections_controller.rb
index 00103d105..f7a87b997 100644
--- a/app/controllers/sections_controller.rb
+++ b/app/controllers/sections_controller.rb
@@ -56,46 +56,48 @@ def display
private
- def set_section
- @section = Section.find_by_id(params[:id])
- return if @section.present?
- redirect_to :root, alert: I18n.t('controllers.no_section')
- end
+ def set_section
+ @section = Section.find_by_id(params[:id])
+ return if @section.present?
- def section_params
- params.require(:section).permit(:title, :display_number, :chapter_id,
- :details, :hidden,
- tag_ids: [], lesson_ids: [])
- end
+ redirect_to :root, alert: I18n.t('controllers.no_section')
+ end
- # inserts the section in the correct position if predecessor is given,
- # otherwise just saves
- def insert_or_save
- position = params[:section][:predecessor]
- if position.present?
- @section.insert_at(position.to_i + 1)
- else
- @section.save
+ def section_params
+ params.require(:section).permit(:title, :display_number, :chapter_id,
+ :details, :hidden,
+ tag_ids: [], lesson_ids: [])
end
- end
- # updates the position of the section if predecessor is given
- def update_position
- predecessor = params[:section][:predecessor]
- return unless predecessor.present?
- position = predecessor.to_i
- if position > @section.position && @old_chapter == @section.chapter
- position -= 1
+ # inserts the section in the correct position if predecessor is given,
+ # otherwise just saves
+ def insert_or_save
+ position = params[:section][:predecessor]
+ if position.present?
+ @section.insert_at(position.to_i + 1)
+ else
+ @section.save
+ end
end
- @section.insert_at(position + 1)
- end
- def update_tags_order
- tags_order = params[:section][:tag_ids].map(&:to_i) - [0]
- SectionTagJoin.acts_as_list_no_update do
- @section.section_tag_joins.each do |st|
- st.update(tag_position: tags_order.index(st.tag_id))
+ # updates the position of the section if predecessor is given
+ def update_position
+ predecessor = params[:section][:predecessor]
+ return unless predecessor.present?
+
+ position = predecessor.to_i
+ if position > @section.position && @old_chapter == @section.chapter
+ position -= 1
+ end
+ @section.insert_at(position + 1)
+ end
+
+ def update_tags_order
+ tags_order = params[:section][:tag_ids].map(&:to_i) - [0]
+ SectionTagJoin.acts_as_list_no_update do
+ @section.section_tag_joins.each do |st|
+ st.update(tag_position: tags_order.index(st.tag_id))
+ end
end
end
- end
end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index ccb2e2f3c..ad3178f19 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -1,8 +1,7 @@
class SessionsController < Devise::SessionsController
-
# remove devise's flash message for succesful sign_in
def create
super
flash.clear
end
-end
\ No newline at end of file
+end
diff --git a/app/controllers/subjects_controller.rb b/app/controllers/subjects_controller.rb
index 1aec93c3f..6cd036d20 100644
--- a/app/controllers/subjects_controller.rb
+++ b/app/controllers/subjects_controller.rb
@@ -12,13 +12,13 @@ def new
authorize! :new, @subject
end
- def edit
- end
+ def edit
+ end
- def update
- @subject.update(subject_params)
- redirect_to classification_path
- end
+ def update
+ @subject.update(subject_params)
+ redirect_to classification_path
+ end
def create
@subject = Subject.new(subject_params)
@@ -34,14 +34,14 @@ def destroy
private
- def set_subject
- @subject = Subject.find_by_id(params[:id])
- return if @subject.present?
+ def set_subject
+ @subject = Subject.find_by_id(params[:id])
+ return if @subject.present?
- redirect_to root_path, alert: I18n.t('controllers.no_answer')
- end
+ redirect_to root_path, alert: I18n.t('controllers.no_answer')
+ end
- def subject_params
- params.require(:subject).permit(*Subject.globalize_attribute_names)
- end
-end
\ No newline at end of file
+ def subject_params
+ params.require(:subject).permit(*Subject.globalize_attribute_names)
+ end
+end
diff --git a/app/controllers/submissions_controller.rb b/app/controllers/submissions_controller.rb
index 442b3ad1e..ad4422df9 100644
--- a/app/controllers/submissions_controller.rb
+++ b/app/controllers/submissions_controller.rb
@@ -23,13 +23,13 @@ def index
@current_assignments = @lecture.current_assignments
@previous_assignments = @lecture.previous_assignments
@old_assignments = @assignments.expired.order('deadline DESC') -
- @previous_assignments
+ @previous_assignments
@future_assignments = @assignments.active.order(:deadline) -
- @current_assignments
+ @current_assignments
end
def new
- @submission = Submission.new
+ @submission = Submission.new
@submission.assignment = @assignment
set_submission_locale
end
@@ -38,7 +38,8 @@ def edit
end
def update
- return if @too_late
+ return if @too_late
+
old_manuscript_data = @submission.manuscript_data
@old_filename = @submission.manuscript_filename
if submission_manuscript_params[:manuscript].present?
@@ -47,6 +48,7 @@ def update
.metadata,
:manuscript)
return if @errors.present?
+
@submission.save
@errors = @submission.errors
return unless @submission.valid?
@@ -67,11 +69,12 @@ def update
end
def create
- @submission = Submission.new(submission_create_params)
+ @submission = Submission.new(submission_create_params)
@lecture = @submission&.assignment&.lecture
set_submission_locale
@too_late = @submission.not_updatable?
- return if @too_late
+ return if @too_late
+
if submission_manuscript_params[:manuscript].present?
@submission.manuscript = submission_manuscript_params[:manuscript]
@errors = @submission.check_file_properties(@submission.manuscript
@@ -84,14 +87,17 @@ def create
@assignment = @submission.assignment
@errors = @submission.errors
return unless @submission.valid?
+
send_invitation_emails
@submission.update(last_modification_by_users_at: Time.now)
return unless @submission.manuscript
+
send_upload_email(User.where(id: current_user.id))
end
def destroy
return if @too_late
+
@submission.destroy
end
@@ -124,6 +130,7 @@ def join
def leave
return if @too_late
+
if @submission.users.count == 1
@error = I18n.t('submission.no_partners_no_leave')
return
@@ -141,8 +148,8 @@ def cancel_new
def show_manuscript
if @submission && @submission.manuscript
send_file @submission.manuscript.to_io,
- type: @submission.manuscript_mime_type,
- disposition: @disposition,
+ type: @submission.manuscript_mime_type,
+ disposition: @disposition,
filename: @submission.manuscript_filename
elsif @submission
redirect_to :start, alert: t('submission.no_manuscript_yet')
@@ -165,20 +172,20 @@ def show_correction
end
def refresh_token
- @submission.update(token: Submission.generate_token)
+ @submission.update(token: Submission.generate_token)
end
def enter_invitees
- @too_late = @submission.assignment.totally_expired?
+ @too_late = @submission.assignment.totally_expired?
end
def invite
- if @too_late
- render :create
- return
- end
- send_invitation_emails
- render :create
+ if @too_late
+ render :create
+ return
+ end
+ send_invitation_emails
+ render :create
end
def edit_correction
@@ -188,12 +195,13 @@ def cancel_edit_correction
end
def add_correction
- if correction_params[:correction].present?
+ if correction_params[:correction].present?
@submission.correction = correction_params[:correction]
@errors = @submission.check_file_properties_any(@submission.correction
.metadata,
- :correction)
+ :correction)
return if @errors.present?
+
@submission.save
@errors = @submission.errors
return unless @submission.valid?
@@ -201,6 +209,7 @@ def add_correction
@submission.update(correction_params)
@errors = @submission.errors
return if @errors.present?
+
send_correction_upload_email(@submission.users)
end
@@ -235,212 +244,220 @@ def reject
private
- def set_submission
- @submission = Submission.find_by_id(params[:id])
- @assignment = @submission&.assignment
- @lecture = @assignment&.lecture
- set_submission_locale
- return if @submission
- flash[:alert] = I18n.t('controllers.no_submission')
- render js: "window.location='#{root_path}'"
- end
+ def set_submission
+ @submission = Submission.find_by_id(params[:id])
+ @assignment = @submission&.assignment
+ @lecture = @assignment&.lecture
+ set_submission_locale
+ return if @submission
- def submission_create_params
- params.require(:submission).permit(:tutorial_id, :assignment_id)
- end
+ flash[:alert] = I18n.t('controllers.no_submission')
+ render js: "window.location='#{root_path}'"
+ end
- # disallow modification of assignment
- def submission_update_params
- params.require(:submission).permit(:tutorial_id)
- end
+ def submission_create_params
+ params.require(:submission).permit(:tutorial_id, :assignment_id)
+ end
- # disallow modification of assignment
- def submission_manuscript_params
- params.require(:submission).permit(:manuscript)
- end
+ # disallow modification of assignment
+ def submission_update_params
+ params.require(:submission).permit(:tutorial_id)
+ end
- def set_assignment
- @assignment = Assignment.find_by_id(params[:assignment_id])
- @lecture = @assignment&.lecture
- set_submission_locale
- return if @assignment
- flash[:alert] = I18n.t('controllers.no_assignment')
- render js: "window.location='#{root_path}'"
- return
- end
+ # disallow modification of assignment
+ def submission_manuscript_params
+ params.require(:submission).permit(:manuscript)
+ end
- def set_lecture
- @lecture = Lecture.find_by_id(params[:id])
- set_submission_locale and return if @lecture
- redirect_to :root, alert: I18n.t('controllers.no_lecture')
- end
+ def set_assignment
+ @assignment = Assignment.find_by_id(params[:assignment_id])
+ @lecture = @assignment&.lecture
+ set_submission_locale
+ return if @assignment
- def set_too_late
- @too_late = @submission.not_updatable?
- end
+ flash[:alert] = I18n.t('controllers.no_assignment')
+ render js: "window.location='#{root_path}'"
+ return
+ end
- def set_submission_locale
- I18n.locale = @lecture&.locale_with_inheritance || current_user.locale ||
+ def set_lecture
+ @lecture = Lecture.find_by_id(params[:id])
+ set_submission_locale and return if @lecture
+
+ redirect_to :root, alert: I18n.t('controllers.no_lecture')
+ end
+
+ def set_too_late
+ @too_late = @submission.not_updatable?
+ end
+
+ def set_submission_locale
+ I18n.locale = @lecture&.locale_with_inheritance || current_user.locale ||
I18n.default_locale
- end
+ end
- def join_params
- params.require(:join).permit(:code, :assignment_id)
- end
+ def join_params
+ params.require(:join).permit(:code, :assignment_id)
+ end
- def invitation_params
- params.require(:submission).permit(invitee_ids: [])
- end
+ def invitation_params
+ params.require(:submission).permit(invitee_ids: [])
+ end
- def correction_params
- params.require(:submission).permit(:correction)
- end
+ def correction_params
+ params.require(:submission).permit(:correction)
+ end
- def move_params
- params.require(:submission).permit(:tutorial_id)
- end
+ def move_params
+ params.require(:submission).permit(:tutorial_id)
+ end
- def send_invitation_emails
- invitees = User.where(id: invitation_params[:invitee_ids])
- invitees.each do |i|
- NotificationMailer.with(recipient: i,
- locale: i.locale,
- assignment: @assignment,
- code: @submission.token,
- issuer: current_user)
- .submission_invitation_email.deliver_later
- end
- @submission.update(invited_user_ids: @submission.invited_user_ids |
- invitees.pluck(:id))
- end
+ def send_invitation_emails
+ invitees = User.where(id: invitation_params[:invitee_ids])
+ invitees.each do |i|
+ NotificationMailer.with(recipient: i,
+ locale: i.locale,
+ assignment: @assignment,
+ code: @submission.token,
+ issuer: current_user)
+ .submission_invitation_email.deliver_later
+ end
+ @submission.update(invited_user_ids: @submission.invited_user_ids |
+ invitees.pluck(:id))
+ end
- def send_upload_email(users)
- users.email_for_submission_upload.each do |u|
- NotificationMailer.with(recipient: u,
- locale: u.locale,
- submission: @submission,
- uploader: current_user,
- filename: @submission.manuscript_filename)
- .submission_upload_email.deliver_later
+ def send_upload_email(users)
+ users.email_for_submission_upload.each do |u|
+ NotificationMailer.with(recipient: u,
+ locale: u.locale,
+ submission: @submission,
+ uploader: current_user,
+ filename: @submission.manuscript_filename)
+ .submission_upload_email.deliver_later
+ end
end
- end
- def send_upload_removal_email(users)
- users.email_for_submission_removal.each do |u|
- NotificationMailer.with(recipient: u,
- locale: u.locale,
- submission: @submission,
- remover: current_user,
- filename: @old_filename)
- .submission_upload_removal_email.deliver_later
+ def send_upload_removal_email(users)
+ users.email_for_submission_removal.each do |u|
+ NotificationMailer.with(recipient: u,
+ locale: u.locale,
+ submission: @submission,
+ remover: current_user,
+ filename: @old_filename)
+ .submission_upload_removal_email.deliver_later
+ end
end
- end
- def send_correction_upload_email(users)
- users.email_for_correction_upload.each do |u|
- NotificationMailer.with(recipient: u,
- locale: u.locale,
- submission: @submission,
- tutor: current_user)
- .correction_upload_email.deliver_later
+ def send_correction_upload_email(users)
+ users.email_for_correction_upload.each do |u|
+ NotificationMailer.with(recipient: u,
+ locale: u.locale,
+ submission: @submission,
+ tutor: current_user)
+ .correction_upload_email.deliver_later
+ end
end
- end
- def send_acceptance_email(users)
- users.email_for_submission_decision.each do |u|
- NotificationMailer.with(recipient: u,
- locale: u.locale,
- submission: @submission)
- .submission_acceptance_email.deliver_later
+ def send_acceptance_email(users)
+ users.email_for_submission_decision.each do |u|
+ NotificationMailer.with(recipient: u,
+ locale: u.locale,
+ submission: @submission)
+ .submission_acceptance_email.deliver_later
+ end
end
- end
- def send_rejection_email(users)
- users.email_for_submission_decision.each do |u|
- NotificationMailer.with(recipient: u,
- locale: u.locale,
- submission: @submission)
- .submission_rejection_email.deliver_later
+ def send_rejection_email(users)
+ users.email_for_submission_decision.each do |u|
+ NotificationMailer.with(recipient: u,
+ locale: u.locale,
+ submission: @submission)
+ .submission_rejection_email.deliver_later
+ end
end
- end
- def check_code_validity
- if !@submission && @assignment
- @error = I18n.t('submission.invalid_code_for_assignment',
- assignment: @assignment.title)
- elsif !@submission
- @error = I18n.t('submission.invalid_code')
- elsif @assignment&.totally_expired?
- @error = I18n.t('submission.assignment_expired')
- elsif @submission.correction
- @error = I18n.t('submission.already_corrected')
- elsif current_user.in?(@submission.users)
- @error = I18n.t('submission.already_in')
- elsif !@submission.tutorial.lecture.in?(current_user.lectures)
- @error = I18n.t('submission.lecture_not_subscribed')
+ def check_code_validity
+ if !@submission && @assignment
+ @error = I18n.t('submission.invalid_code_for_assignment',
+ assignment: @assignment.title)
+ elsif !@submission
+ @error = I18n.t('submission.invalid_code')
+ elsif @assignment&.totally_expired?
+ @error = I18n.t('submission.assignment_expired')
+ elsif @submission.correction
+ @error = I18n.t('submission.already_corrected')
+ elsif current_user.in?(@submission.users)
+ @error = I18n.t('submission.already_in')
+ elsif !@submission.tutorial.lecture.in?(current_user.lectures)
+ @error = I18n.t('submission.lecture_not_subscribed')
+ end
end
- end
- def check_code_and_join
- check_code_validity
- unless @error
- @join = UserSubmissionJoin.new(user: current_user,
- submission: @submission)
- @join.save
- if @join.valid?
- @submission.update(last_modification_by_users_at: Time.now)
- send_join_email
- remove_invitee_status
- else
- @error = @join.errors[:base].join(', ')
- end
+ def check_code_and_join
+ check_code_validity
+ unless @error
+ @join = UserSubmissionJoin.new(user: current_user,
+ submission: @submission)
+ @join.save
+ if @join.valid?
+ @submission.update(last_modification_by_users_at: Time.now)
+ send_join_email
+ remove_invitee_status
+ else
+ @error = @join.errors[:base].join(', ')
+ end
+ end
end
- end
- def send_join_email
- (@submission.users.email_for_submission_join - [current_user]).each do |u|
- NotificationMailer.with(recipient: u,
- locale: u.locale,
- submission: @submission,
- user: current_user)
- .submission_join_email.deliver_later
+ def send_join_email
+ (@submission.users.email_for_submission_join - [current_user]).each do |u|
+ NotificationMailer.with(recipient: u,
+ locale: u.locale,
+ submission: @submission,
+ user: current_user)
+ .submission_join_email.deliver_later
+ end
end
- end
- def send_leave_email
- (@submission.users.email_for_submission_leave - [current_user]).each do |u|
- NotificationMailer.with(recipient: u,
- locale: u.locale,
- submission: @submission,
- user: current_user)
- .submission_leave_email.deliver_later
+ def send_leave_email
+ (@submission.users.email_for_submission_leave - [current_user]).each do |u|
+ NotificationMailer.with(recipient: u,
+ locale: u.locale,
+ submission: @submission,
+ user: current_user)
+ .submission_leave_email.deliver_later
+ end
end
- end
- def remove_invitee_status
- @submission.update(invited_user_ids: @submission.invited_user_ids -
- [current_user.id])
- end
+ def remove_invitee_status
+ @submission.update(invited_user_ids: @submission.invited_user_ids -
+ [current_user.id])
+ end
- def check_student_status
- return if current_user.proper_student_in?(@lecture)
- redirect_to :root, alert: I18n.t('controllers.no_student_status_in_lecture')
- end
+ def check_student_status
+ return if current_user.proper_student_in?(@lecture)
- def check_if_tutorials
- return if @lecture.tutorials.any?
- redirect_to :root, alert: I18n.t('controllers.no_tutorials_in_lecture')
- end
+ redirect_to :root,
+ alert: I18n.t('controllers.no_student_status_in_lecture')
+ end
- def check_if_assignments
- return if @lecture.assignments.any?
- redirect_to :root, alert: I18n.t('controllers.no_assignments_in_lecture')
- end
+ def check_if_tutorials
+ return if @lecture.tutorials.any?
- def set_disposition
- @disposition = params[:download] == 'true' ? 'attachment' : 'inline'
- accepted = @submission.assignment.accepted_file_type
- return unless accepted.in?(Assignment.non_inline_file_types)
- @disposition = 'attachment'
- end
-end
\ No newline at end of file
+ redirect_to :root, alert: I18n.t('controllers.no_tutorials_in_lecture')
+ end
+
+ def check_if_assignments
+ return if @lecture.assignments.any?
+
+ redirect_to :root, alert: I18n.t('controllers.no_assignments_in_lecture')
+ end
+
+ def set_disposition
+ @disposition = params[:download] == 'true' ? 'attachment' : 'inline'
+ accepted = @submission.assignment.accepted_file_type
+ return unless accepted.in?(Assignment.non_inline_file_types)
+
+ @disposition = 'attachment'
+ end
+end
diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb
index a27e4eafa..574a42d84 100644
--- a/app/controllers/tags_controller.rb
+++ b/app/controllers/tags_controller.rb
@@ -11,7 +11,6 @@ class TagsController < ApplicationController
:render_tag_title]
layout 'administration'
-
def current_ability
@current_ability ||= TagAbility.new(current_user)
end
@@ -62,6 +61,7 @@ def new
def update
# first, check if errors from check_permission callback are present
return if @errors.present?
+
@tag.update(tag_params)
if @tag.valid?
@tag.update(realizations: realization_params)
@@ -144,10 +144,10 @@ def search
fulltext search_params[:title]
end
course_ids = if search_params[:all_courses] == '1'
- []
- elsif search_params[:course_ids] != ['']
- search_params[:course_ids]
- end
+ []
+ elsif search_params[:course_ids] != ['']
+ search_params[:course_ids]
+ end
search.build do
with(:course_ids, course_ids)
paginate page: params[:page], per_page: per_page
@@ -170,10 +170,13 @@ def postprocess
@tags_hash.each do |t, section_data|
tag = Tag.find_by_id(t)
next unless tag
+
section_data.each do |s, v|
next if v.to_i == 0
+
section = Section.find(s)
next unless section
+
if !tag.in?(section.tags)
section.tags << tag
end
@@ -195,175 +198,176 @@ def render_tag_title
private
- def set_tag
- @tag = Tag.find_by_id(params[:id])
- return if @tag.present?
- redirect_to :root, alert: I18n.t('controllers.no_tag')
- end
+ def set_tag
+ @tag = Tag.find_by_id(params[:id])
+ return if @tag.present?
- # set up cytoscape graph data for neighbourhood subgraph of @tag,
- # using only neighbourhood tags that are allowd by the user's
- # profile settings, depending on the parameters (selection/depth) that were
- # specified by the user)
- def set_related_tags_for_user
- @depth = 2
- depth_param = params[:depth].to_i
- @depth = depth_param if depth_param.in?([1, 2])
- overrule_subscription_type = false
- selection = params[:selection].to_i
- if selection.in?([1, 2, 3])
- overrule_subscription_type = selection
- end
- @selection_type = if overrule_subscription_type
- selection
- else
- current_user.subscription_type
- end
- user_tags = current_user.visible_tags(overrule_subscription_type: overrule_subscription_type)
- @related_tags = @tag.related_tags & user_tags
- @tags_in_neighbourhood = if @depth == 2
- Tag.related_tags(@related_tags) & user_tags
- else
- []
- end
- @tags = [@tag] + @related_tags + @tags_in_neighbourhood
- @graph_elements = Tag.to_cytoscape(@tags, @tag,
- highlight_related_tags: @depth == 2)
- end
+ redirect_to :root, alert: I18n.t('controllers.no_tag')
+ end
- # set up cytoscape graph data for neighbourhood subgraph of @tag,
- def set_related_tags
- related_tags = @tag.related_tags
- tags_in_neighbourhood = Tag.related_tags(related_tags)
- @graph_elements = Tag.to_cytoscape([@tag] + related_tags +
- tags_in_neighbourhood, @tag)
- end
+ # set up cytoscape graph data for neighbourhood subgraph of @tag,
+ # using only neighbourhood tags that are allowd by the user's
+ # profile settings, depending on the parameters (selection/depth) that were
+ # specified by the user)
+ def set_related_tags_for_user
+ @depth = 2
+ depth_param = params[:depth].to_i
+ @depth = depth_param if depth_param.in?([1, 2])
+ overrule_subscription_type = false
+ selection = params[:selection].to_i
+ if selection.in?([1, 2, 3])
+ overrule_subscription_type = selection
+ end
+ @selection_type = if overrule_subscription_type
+ selection
+ else
+ current_user.subscription_type
+ end
+ user_tags = current_user.visible_tags(overrule_subscription_type: overrule_subscription_type)
+ @related_tags = @tag.related_tags & user_tags
+ @tags_in_neighbourhood = if @depth == 2
+ Tag.related_tags(@related_tags) & user_tags
+ else
+ []
+ end
+ @tags = [@tag] + @related_tags + @tags_in_neighbourhood
+ @graph_elements = Tag.to_cytoscape(@tags, @tag,
+ highlight_related_tags: @depth == 2)
+ end
- def set_up_tag
- @tag = Tag.new
- set_notions
- related_tag = Tag.find_by_id(params[:related_tag])
- @tag.related_tags << related_tag if related_tag.present?
- end
+ # set up cytoscape graph data for neighbourhood subgraph of @tag,
+ def set_related_tags
+ related_tags = @tag.related_tags
+ tags_in_neighbourhood = Tag.related_tags(related_tags)
+ @graph_elements = Tag.to_cytoscape([@tag] + related_tags +
+ tags_in_neighbourhood, @tag)
+ end
- def add_course
- course = Course.find_by_id(params[:course])
- @tag.courses << course if course.present?
- end
+ def set_up_tag
+ @tag = Tag.new
+ set_notions
+ related_tag = Tag.find_by_id(params[:related_tag])
+ @tag.related_tags << related_tag if related_tag.present?
+ end
- def add_section
- section = Section.find_by_id(params[:section])
- if section
- @tag.sections << section
- I18n.locale = section.lecture.locale || current_user.locale
+ def add_course
+ course = Course.find_by_id(params[:course])
+ @tag.courses << course if course.present?
end
- end
- def add_medium
- medium = Medium.find_by_id(params[:medium])
- if medium
+ def add_section
+ section = Section.find_by_id(params[:section])
+ if section
+ @tag.sections << section
+ I18n.locale = section.lecture.locale || current_user.locale
+ end
+ end
+
+ def add_medium
+ medium = Medium.find_by_id(params[:medium])
+ if medium
I18n.locale = medium.locale_with_inheritance || current_user.locale
@tag.media << medium
+ end
end
- end
- def add_lesson
- lesson = Lesson.find_by_id(params[:lesson])
- if lesson
- @tag.lessons << lesson
- I18n.locale = lesson.lecture.locale || current_user.locale
+ def add_lesson
+ lesson = Lesson.find_by_id(params[:lesson])
+ if lesson
+ @tag.lessons << lesson
+ I18n.locale = lesson.lecture.locale || current_user.locale
+ end
end
- end
- def add_talk
- talk = Talk.find_by_id(params[:talk])
- if talk
- @tag.talks << talk
- I18n.locale = talk.lecture.locale || current_user.locale
+ def add_talk
+ talk = Talk.find_by_id(params[:talk])
+ if talk
+ @tag.talks << talk
+ I18n.locale = talk.lecture.locale || current_user.locale
+ end
end
- end
- def check_for_consent
- redirect_to consent_profile_path unless current_user.consents
- end
+ def check_for_consent
+ redirect_to consent_profile_path unless current_user.consents
+ end
- def tag_params
- params.require(:tag).permit(related_tag_ids: [],
- notions_attributes: [:title, :locale, :id,
- :_destroy],
- aliases_attributes: [:title, :locale, :id,
- :_destroy],
- course_ids: [],
- section_ids: [],
- lesson_ids: [],
- talk_ids: [],
- media_ids: [])
- end
+ def tag_params
+ params.require(:tag).permit(related_tag_ids: [],
+ notions_attributes: [:title, :locale, :id,
+ :_destroy],
+ aliases_attributes: [:title, :locale, :id,
+ :_destroy],
+ course_ids: [],
+ section_ids: [],
+ lesson_ids: [],
+ talk_ids: [],
+ media_ids: [])
+ end
- def realization_params
- (params.require(:tag).permit(realizations: [])[:realizations] - [''])
- .map { |r| r.split('-') }
- .map { |x| [x.first, x.second.to_i] }
- end
+ def realization_params
+ (params.require(:tag).permit(realizations: [])[:realizations] - [''])
+ .map { |r| r.split('-') }
+ .map { |x| [x.first, x.second.to_i] }
+ end
- def check_permissions
- @errors = {}
- return if current_user.admin?
- # of current user is not an admin, he can add/remove courses only
- # as course editor with inheritance/course_editor
- permission_errors
- end
+ def check_permissions
+ @errors = {}
+ return if current_user.admin?
- def permission_errors
- errors = []
- unless removed_courses.all? { |c| c.removable_by?(current_user) }
- errors.push(error_hash['remove_course'])
- end
- unless added_courses.all? { |c| c.addable_by?(current_user) }
- errors.push(error_hash['add_course'])
+ # of current user is not an admin, he can add/remove courses only
+ # as course editor with inheritance/course_editor
+ permission_errors
end
- @errors[:courses] = errors if errors.present?
- end
- def check_creation_permission
- @modal = (params[:tag][:modal] == 'true')
- @tag = Tag.new
- check_permissions
- end
+ def permission_errors
+ errors = []
+ unless removed_courses.all? { |c| c.removable_by?(current_user) }
+ errors.push(error_hash['remove_course'])
+ end
+ unless added_courses.all? { |c| c.addable_by?(current_user) }
+ errors.push(error_hash['add_course'])
+ end
+ @errors[:courses] = errors if errors.present?
+ end
- def removed_courses
- @tag.courses - Course.where(id: tag_params[:course_ids])
- end
+ def check_creation_permission
+ @modal = (params[:tag][:modal] == 'true')
+ @tag = Tag.new
+ check_permissions
+ end
- def added_courses
- Course.where(id: tag_params[:course_ids]) - @tag.courses
- end
+ def removed_courses
+ @tag.courses - Course.where(id: tag_params[:course_ids])
+ end
- def set_notions
- @tag.notions.new(locale: I18n.locale)
- (I18n.available_locales - [I18n.locale]).each do |l|
- @tag.notions.new(locale: l)
+ def added_courses
+ Course.where(id: tag_params[:course_ids]) - @tag.courses
end
- end
- def locale
- locale = if params[:from] == 'course'
- @tag.courses&.first&.locale
- elsif params[:from] == 'medium'
- @tag.media&.first&.locale_with_inheritance
- elsif params[:from] == 'section'
- @tag.sections&.first&.lecture&.locale_with_inheritance
- end
- locale || current_user.locale
- end
+ def set_notions
+ @tag.notions.new(locale: I18n.locale)
+ (I18n.available_locales - [I18n.locale]).each do |l|
+ @tag.notions.new(locale: l)
+ end
+ end
- def error_hash
- { 'remove_course' => I18n.t('controllers.no_removal_rights'),
- 'add_course' => I18n.t('controllers.no_adding_rights') }
- end
+ def locale
+ locale = if params[:from] == 'course'
+ @tag.courses&.first&.locale
+ elsif params[:from] == 'medium'
+ @tag.media&.first&.locale_with_inheritance
+ elsif params[:from] == 'section'
+ @tag.sections&.first&.lecture&.locale_with_inheritance
+ end
+ locale || current_user.locale
+ end
- def search_params
- params.require(:search).permit(:title, :all_courses, :per, course_ids: [])
- end
+ def error_hash
+ { 'remove_course' => I18n.t('controllers.no_removal_rights'),
+ 'add_course' => I18n.t('controllers.no_adding_rights') }
+ end
+ def search_params
+ params.require(:search).permit(:title, :all_courses, :per, course_ids: [])
+ end
end
diff --git a/app/controllers/terms_controller.rb b/app/controllers/terms_controller.rb
index 6717853d3..af473afe0 100644
--- a/app/controllers/terms_controller.rb
+++ b/app/controllers/terms_controller.rb
@@ -66,18 +66,19 @@ def set_active
private
- def set_term
- @id = params[:id]
- @term = Term.find_by_id(@id)
- return if @term
- redirect_to terms_path, alert: I18n.t('controllers.no_term')
- end
+ def set_term
+ @id = params[:id]
+ @term = Term.find_by_id(@id)
+ return if @term
- def term_params
- params.require(:term).permit(:year, :season)
- end
+ redirect_to terms_path, alert: I18n.t('controllers.no_term')
+ end
- def active_term_params
- params.permit(:active_term)
- end
+ def term_params
+ params.require(:term).permit(:year, :season)
+ end
+
+ def active_term_params
+ params.permit(:active_term)
+ end
end
diff --git a/app/controllers/tutorials_controller.rb b/app/controllers/tutorials_controller.rb
index 9bbcfc12a..f849a708a 100644
--- a/app/controllers/tutorials_controller.rb
+++ b/app/controllers/tutorials_controller.rb
@@ -26,7 +26,7 @@ def index
authorize! :index, Tutorial.new, @lecture
@assignments = @lecture.assignments.order('deadline DESC')
@assignment = Assignment.find_by_id(params[:assignment]) ||
- @assignments&.first
+ @assignments&.first
if current_user.editor_or_teacher_in?(@lecture)
@tutorials = @lecture.tutorials
else
@@ -41,7 +41,7 @@ def overview
authorize! :overview, Tutorial.new, @lecture
@assignments = @lecture.assignments.order('deadline DESC')
@assignment = Assignment.find_by_id(params[:assignment]) ||
- @assignments&.first
+ @assignments&.first
@tutorials = @lecture.tutorials
end
@@ -117,81 +117,88 @@ def validate_certificate
def export_teams
respond_to do |format|
format.html { head :ok }
- format.csv { send_data @tutorial.teams_to_csv(@assignment),
- filename: "#{@tutorial.title}-#{@assignment.title}.csv" }
+ format.csv {
+ send_data @tutorial.teams_to_csv(@assignment),
+ filename: "#{@tutorial.title}-#{@assignment.title}.csv"
+ }
end
end
private
- def set_tutorial
- @tutorial = Tutorial.find_by_id(params[:id])
- @lecture = @tutorial&.lecture
- set_tutorial_locale and return if @tutorial
- redirect_to :root, alert: I18n.t('controllers.no_tutorial')
- end
+ def set_tutorial
+ @tutorial = Tutorial.find_by_id(params[:id])
+ @lecture = @tutorial&.lecture
+ set_tutorial_locale and return if @tutorial
- def set_assignment
- @assignment = Assignment.find_by_id(params[:ass_id])
- return if @assignment
- redirect_to :root, alert: I18n.t('controllers.no_assignment')
- end
+ redirect_to :root, alert: I18n.t('controllers.no_tutorial')
+ end
- def set_lecture
- @lecture = Lecture.find_by_id(params[:id])
- set_tutorial_locale and return if @lecture
- redirect_to :root, alert: I18n.t('controllers.no_lecture')
- end
+ def set_assignment
+ @assignment = Assignment.find_by_id(params[:ass_id])
+ return if @assignment
- def set_lecture_from_form
- @lecture = Lecture.find_by_id(tutorial_params[:lecture_id])
- return if @lecture
- redirect_to :root, alert: I18n.t('controllers.no_lecture')
- end
+ redirect_to :root, alert: I18n.t('controllers.no_assignment')
+ end
+
+ def set_lecture
+ @lecture = Lecture.find_by_id(params[:id])
+ set_tutorial_locale and return if @lecture
- def set_tutorial_locale
- I18n.locale = @lecture&.locale_with_inheritance || current_user.locale ||
+ redirect_to :root, alert: I18n.t('controllers.no_lecture')
+ end
+
+ def set_lecture_from_form
+ @lecture = Lecture.find_by_id(tutorial_params[:lecture_id])
+ return if @lecture
+
+ redirect_to :root, alert: I18n.t('controllers.no_lecture')
+ end
+
+ def set_tutorial_locale
+ I18n.locale = @lecture&.locale_with_inheritance || current_user.locale ||
I18n.default_locale
- end
+ end
- def can_view_index
- return if current_user.in?(@lecture.tutors) || current_user.editor_or_teacher_in?(@lecture)
- redirect_to :root, alert: I18n.t('controllers.no_tutor_in_this_lecture')
- end
+ def can_view_index
+ return if current_user.in?(@lecture.tutors) || current_user.editor_or_teacher_in?(@lecture)
- def tutorial_params
- params.require(:tutorial).permit(:title, :lecture_id, tutor_ids: [])
- end
+ redirect_to :root, alert: I18n.t('controllers.no_tutor_in_this_lecture')
+ end
- def bulk_params
- params.permit(:package)
- end
+ def tutorial_params
+ params.require(:tutorial).permit(:title, :lecture_id, tutor_ids: [])
+ end
- def bulk_download(zipped, end_of_file='')
- if zipped.is_a?(StringIO)
- send_data zipped.read,
- filename: @assignment.title + '@' + @tutorial.title + end_of_file + '.zip',
- type: 'application/zip',
- disposition: 'attachment'
- else
- flash[:alert] = I18n.t('controllers.tutorials.bulk_download_failed',
- message: zipped)
- redirect_to lecture_tutorials_path(@tutorial.lecture,
- params:
- { assignment: @assignment.id,
- tutorial: @tutorial.id })
+ def bulk_params
+ params.permit(:package)
end
- end
- def send_correction_upload_emails
- @report[:successful_saves]&.each do |submission|
- submission.users.email_for_correction_upload.each do |u|
- NotificationMailer.with(recipient: u,
- locale: u.locale,
- submission: submission,
- tutor: current_user)
- .correction_upload_email.deliver_later
+ def bulk_download(zipped, end_of_file = '')
+ if zipped.is_a?(StringIO)
+ send_data zipped.read,
+ filename: @assignment.title + '@' + @tutorial.title + end_of_file + '.zip',
+ type: 'application/zip',
+ disposition: 'attachment'
+ else
+ flash[:alert] = I18n.t('controllers.tutorials.bulk_download_failed',
+ message: zipped)
+ redirect_to lecture_tutorials_path(@tutorial.lecture,
+ params:
+ { assignment: @assignment.id,
+ tutorial: @tutorial.id })
end
end
- end
-end
\ No newline at end of file
+
+ def send_correction_upload_emails
+ @report[:successful_saves]&.each do |submission|
+ submission.users.email_for_correction_upload.each do |u|
+ NotificationMailer.with(recipient: u,
+ locale: u.locale,
+ submission: submission,
+ tutor: current_user)
+ .correction_upload_email.deliver_later
+ end
+ end
+ end
+end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 405e20bf7..0ed0ae4c2 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -39,6 +39,7 @@ def elevate
@user = User.find(elevate_params[:id])
admin = elevate_params[:admin] == '1'
return unless admin
+
# enforce a name
if @user.name.blank?
name = @user.email.split('@')[0]
@@ -90,23 +91,25 @@ def delete_account
private
- def elevate_params
- params.require(:generic_user).permit(:id, :admin, :editor, :teacher, :name)
- end
+ def elevate_params
+ params.require(:generic_user).permit(:id, :admin, :editor, :teacher,
+ :name)
+ end
- def user_params
- params.require(:user).permit(:name, :email, :homepage,
- :current_lecture_id,:image)
- end
+ def user_params
+ params.require(:user).permit(:name, :email, :homepage,
+ :current_lecture_id, :image)
+ end
- def set_user
- @user = User.find_by_id(params[:id])
- return unless @user.nil?
- redirect_to :root, alert: I18n.t('controllers.no_medium')
- end
+ def set_user
+ @user = User.find_by_id(params[:id])
+ return unless @user.nil?
- def set_elevated_users
- @elevated_users = User.where(admin: true).or(User.proper_editors)
- .or(User.teachers)
- end
-end
\ No newline at end of file
+ redirect_to :root, alert: I18n.t('controllers.no_medium')
+ end
+
+ def set_elevated_users
+ @elevated_users = User.where(admin: true).or(User.proper_editors)
+ .or(User.teachers)
+ end
+end
diff --git a/app/controllers/vertices_controller.rb b/app/controllers/vertices_controller.rb
index 776389313..3f3e027d9 100644
--- a/app/controllers/vertices_controller.rb
+++ b/app/controllers/vertices_controller.rb
@@ -50,51 +50,54 @@ def destroy
private
- def set_values
- @quiz_id = params[:quiz_id]
- @quiz = Quiz.find_by_id(@quiz_id)
- @params_v = params[:vertex]
- end
+ def set_values
+ @quiz_id = params[:quiz_id]
+ @quiz = Quiz.find_by_id(@quiz_id)
+ @params_v = params[:vertex]
+ end
- def set_update_vertex_params
- @vertex_id = @params_v[:vertex_id].to_i
- @branching = {}
- set_branching_hash
- set_hide_array
- end
+ def set_update_vertex_params
+ @vertex_id = @params_v[:vertex_id].to_i
+ @branching = {}
+ set_branching_hash
+ set_hide_array
+ end
- def set_create_vertex_params
- @sort = @params_v[:sort]
- if @sort == 'import'
- @quizzables = Medium.where(id: @params_v[:quizzable_ids],
- type: ['Question', 'Remark'])
- @success = @quizzables.any?
- else
- quizzable = @sort.constantize.create_prefilled(@params_v[:label],
- @quiz.teachable,
- @quiz.editors)
- @success = quizzable.valid?
- @quizzables = [quizzable]
+ def set_create_vertex_params
+ @sort = @params_v[:sort]
+ if @sort == 'import'
+ @quizzables = Medium.where(id: @params_v[:quizzable_ids],
+ type: ['Question', 'Remark'])
+ @success = @quizzables.any?
+ else
+ quizzable = @sort.constantize.create_prefilled(@params_v[:label],
+ @quiz.teachable,
+ @quiz.editors)
+ @success = quizzable.valid?
+ @quizzables = [quizzable]
+ end
end
- end
- def set_branching_hash
- @branching = {}
- @params_v.keys.select { |k| k.start_with?('branching-') }.each do |k|
- next if @params_v[k].to_i == 0
- @branching[k.remove('branching-').to_h] = [@vertex_id, @params_v[k].to_i]
+ def set_branching_hash
+ @branching = {}
+ @params_v.keys.select { |k| k.start_with?('branching-') }.each do |k|
+ next if @params_v[k].to_i == 0
+
+ @branching[k.remove('branching-').to_h] =
+ [@vertex_id, @params_v[k].to_i]
+ end
end
- end
- def set_hide_array
- @hide = @params_v.keys.select { |k| k.start_with?('hide-') }
- .select { |h| @params_v[h] == '1' }
- .map { |h| h.remove('hide-').to_h }
- end
+ def set_hide_array
+ @hide = @params_v.keys.select { |k| k.start_with?('hide-') }
+ .select { |h| @params_v[h] == '1' }
+ .map { |h| h.remove('hide-').to_h }
+ end
- def check_permission
- return if current_user.admin
- return if current_user.can_edit?(@quiz)
- redirect_to :root, alert: I18n.t('controllers.unauthorized')
- end
+ def check_permission
+ return if current_user.admin
+ return if current_user.can_edit?(@quiz)
+
+ redirect_to :root, alert: I18n.t('controllers.unauthorized')
+ end
end
diff --git a/app/controllers/watchlist_entries_controller.rb b/app/controllers/watchlist_entries_controller.rb
index f41c37de8..106e8644e 100644
--- a/app/controllers/watchlist_entries_controller.rb
+++ b/app/controllers/watchlist_entries_controller.rb
@@ -1,6 +1,5 @@
# WatchlistEntriesController
class WatchlistEntriesController < ApplicationController
-
def current_ability
@current_ability ||= WatchlistEntryAbility.new(current_user)
end
diff --git a/app/controllers/watchlists_controller.rb b/app/controllers/watchlists_controller.rb
index 77bff44a2..fc616dbf9 100644
--- a/app/controllers/watchlists_controller.rb
+++ b/app/controllers/watchlists_controller.rb
@@ -71,6 +71,7 @@ def show
authorize! :show, @watchlist
@watchlists = current_user.watchlists
return if @watchlist.watchlist_entries.empty?
+
@watchlist_entries = paginated_results
@media = @watchlist_entries.pluck(:medium_id)
end
@@ -81,7 +82,6 @@ def add_medium
@medium = Medium.find_by_id(params[:medium_id])
end
-
def update_order
entries = params[:order].map { |id| WatchlistEntry.find_by_id(id) }
authorize! :update_order, @watchlist, entries
@@ -104,9 +104,11 @@ def change_visibility
end
private
+
def set_watchlist
@watchlist = Watchlist.find_by_id(params[:id])
return if @watchlist.present?
+
redirect_to :root, alert: I18n.t('controllers.no_watchlist')
end
@@ -130,6 +132,7 @@ def paginated_results
def filter_results
filter_results = @watchlist.watchlist_entries
return filter_results unless params[:reverse]
+
filter_results.reverse
end
@@ -140,5 +143,4 @@ def update_params
def create_params
params.require(:watchlist).permit(:name, :description, :medium_id)
end
-
-end
\ No newline at end of file
+end
diff --git a/app/helpers/announcements_helper.rb b/app/helpers/announcements_helper.rb
index 28203725c..9994c564b 100644
--- a/app/helpers/announcements_helper.rb
+++ b/app/helpers/announcements_helper.rb
@@ -6,6 +6,7 @@ def announcement_notification_item_header(announcement)
unless announcement.lecture.present?
return t('notifications.mampf_announcement')
end
+
t('notifications.lecture_announcement',
title: announcement.lecture.title_for_viewers)
end
@@ -14,6 +15,7 @@ def announcement_notification_item_header(announcement)
def news_card_color(announcement)
return '' unless user_signed_in?
return 'bg-post-it-blue' if announcement.active?(current_user)
+
''
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index c88cfef2e..23fb3040c 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -1,10 +1,10 @@
# ApplicationHelper module
module ApplicationHelper
-
- #returns the path that is associated to the MaMpf brand in the navbar
+ # returns the path that is associated to the MaMpf brand in the navbar
def home_path
return start_path if user_signed_in?
- root_path(params: { locale: I18n.locale})
+
+ root_path(params: { locale: I18n.locale })
end
# get current lecture from session object
@@ -30,6 +30,7 @@ def download_host
def full_title(page_title = '')
return page_title if action_name == 'play' && controller_name == 'media'
return 'Quiz' if action_name == 'take' && controller_name == 'quizzes'
+
base_title = 'MaMpf'
if user_signed_in? && current_user.notifications.any?
base_title += " (#{current_user.notifications.size})"
@@ -109,7 +110,7 @@ def media_names
# Selects all media associated to lectures and lessons from a given list
# of media
def lecture_media(media)
- media.where(teachable_type: ['Lecture', 'Lesson'] )
+ media.where(teachable_type: ['Lecture', 'Lesson'])
end
# Selects all media associated to courses from a given list of media
@@ -121,10 +122,10 @@ def course_media(media)
# the given media are associated to.
def lecture_course_teachables(media)
teachables = media.pluck(:teachable_type, :teachable_id).uniq
- course_ids = teachables.select { |t| t.first == 'Course'}.map(&:second)
- lecture_ids = teachables.select { |t| t.first == 'Lecture'}.map(&:second)
- lesson_ids = teachables.select { |t| t.first == 'Lesson'}.map(&:second)
- talk_ids = teachables.select { |t| t.first == 'Talk'}.map(&:second)
+ course_ids = teachables.select { |t| t.first == 'Course' }.map(&:second)
+ lecture_ids = teachables.select { |t| t.first == 'Lecture' }.map(&:second)
+ lesson_ids = teachables.select { |t| t.first == 'Lesson' }.map(&:second)
+ talk_ids = teachables.select { |t| t.first == 'Talk' }.map(&:second)
lecture_ids += Lesson.where(id: lesson_ids).pluck(:lecture_id).uniq
lecture_ids += Talk.where(id: talk_ids).pluck(:lecture_id).uniq
Course.where(id: course_ids) + Lecture.where(id: lecture_ids.uniq)
@@ -139,8 +140,8 @@ def relevant_media(teachable, media, limit)
result = []
if teachable.class == Course
return media.where(teachable: teachable).order(:created_at)
- .reverse_order
- .first(limit)
+ .reverse_order
+ .first(limit)
end
media_ids = (teachable.media_with_inheritance.pluck(:id) & media.pluck(:id))
Medium.where(id: media_ids).order(:created_at).reverse_order.first(limit)
@@ -152,6 +153,7 @@ def split_list(list, pieces = 4)
groups = list.in_groups_of(group_size)
diff = groups.count - pieces
return groups if diff <= 0
+
tail = groups.pop(diff).first(diff).flatten
groups.last.concat(tail)
groups
@@ -160,6 +162,7 @@ def split_list(list, pieces = 4)
# returns true for 'media#enrich' action
def enrich?(controller, action)
return true if controller == 'media' && action == 'enrich'
+
false
end
@@ -168,6 +171,7 @@ def enrich?(controller, action)
def shorten(title, max_letters)
return '' unless title.present?
return title unless title.length > max_letters
+
title[0, max_letters - 3] + '...'
end
@@ -176,7 +180,8 @@ def shorten(title, max_letters)
def grouped_teachable_list
list = []
Course.all.each do |c|
- lectures = [[c.short_title + ' (' + t('basics.all') + ')', 'Course-' + c.id.to_s]]
+ lectures = [[c.short_title + ' (' + t('basics.all') + ')',
+ 'Course-' + c.id.to_s]]
c.lectures.includes(:term).each do |l|
lectures.push [l.short_title_release, 'Lecture-' + l.id.to_s]
end
@@ -206,6 +211,7 @@ def grouped_teachable_list_alternative
# can edit all lectures associated to the course.
def edit_or_show_lecture_path(lecture)
return edit_lecture_path(lecture) if current_user.can_edit?(lecture)
+
lecture_path(lecture)
end
@@ -217,6 +223,7 @@ def edit_or_inspect_medium_path(medium)
medium.editors_with_inheritance.include?(current_user)
return edit_medium_path(medium)
end
+
inspect_medium_path(medium)
end
@@ -224,10 +231,11 @@ def edit_or_inspect_medium_path(medium)
# anything older than today or yesterday gets reduced to the day.month.year
# yesterday's/today's dates are return as 'gestern/heute' plus hour:mins
def human_readable_date(date)
- return t('today')+ ', ' + date.strftime('%H:%M') if date.to_date == Date.today
+ return t('today') + ', ' + date.strftime('%H:%M') if date.to_date == Date.today
if date.to_date == Date.yesterday
return t('yesterday') + ', ' + date.strftime('%H:%M')
end
+
I18n.localize date, format: :concise
end
@@ -266,12 +274,12 @@ def hide_as_class(value)
def helpdesk(text, html)
tag.i class: 'far fa-question-circle helpdesk ml-2',
- tabindex: -1,
- data: { toggle: 'popover',
- trigger: 'focus',
- content: text,
- html: html },
- title: t('info')
+ tabindex: -1,
+ data: { toggle: 'popover',
+ trigger: 'focus',
+ content: text,
+ html: html },
+ title: t('info')
end
def realization_path(realization)
@@ -291,7 +299,7 @@ def get_announcements
# Navbar items styling based on which page we are on
# https://gist.github.com/mynameispj/5692162
$active_css_class = "active-item"
-
+
def get_class_for_project(project)
return request.params['project'] == project ? $active_css_class : ''
end
@@ -310,9 +318,9 @@ def get_class_for_any_path(paths)
def get_class_for_any_path_startswith(paths)
if paths.any? { |path| request.path.starts_with?(path) }
- return $active_css_class
+ return $active_css_class
end
+
return ''
end
-
end
diff --git a/app/helpers/assignments_helper.rb b/app/helpers/assignments_helper.rb
index d61d3c0aa..ce0369e2f 100644
--- a/app/helpers/assignments_helper.rb
+++ b/app/helpers/assignments_helper.rb
@@ -2,11 +2,13 @@
module AssignmentsHelper
def cancel_editing_assignment_path(assignment)
return cancel_edit_assignment_path(assignment) if assignment.persisted?
+
cancel_new_assignment_path(params: { lecture: assignment.lecture })
end
def has_documents?(assignment)
return false unless assignment.medium
+
assignment.medium.video || assignment.medium.manuscript ||
assignment.medium.geogebra ||
assignment.medium.external_reference_link.present? ||
@@ -15,6 +17,7 @@ def has_documents?(assignment)
def file_button_text(assignment)
return I18n.t('basics.file') unless assignment.accepted_file_type == '.pdf'
+
I18n.t('basics.files')
end
end
diff --git a/app/helpers/chapters_helper.rb b/app/helpers/chapters_helper.rb
index ac711d717..8d806f67b 100644
--- a/app/helpers/chapters_helper.rb
+++ b/app/helpers/chapters_helper.rb
@@ -4,4 +4,4 @@ def chapter_positions_for_select(chapter)
[[t('basics.at_the_beginning'), 0]] + chapter.lecture.select_chapters -
[[chapter.to_label, chapter.position]]
end
-end
\ No newline at end of file
+end
diff --git a/app/helpers/clickers_helper.rb b/app/helpers/clickers_helper.rb
index 58f2f2c72..cde787a1e 100644
--- a/app/helpers/clickers_helper.rb
+++ b/app/helpers/clickers_helper.rb
@@ -10,4 +10,4 @@ def generate_qr(text)
base64_output = Base64.encode64(qrcode.to_png({ xdim: 8 }))
"data:image/png;base64,#{base64_output}"
end
-end
\ No newline at end of file
+end
diff --git a/app/helpers/courses_helper.rb b/app/helpers/courses_helper.rb
index 34d9a028c..7b1758916 100644
--- a/app/helpers/courses_helper.rb
+++ b/app/helpers/courses_helper.rb
@@ -27,6 +27,7 @@ def course_link_or_text(course, user)
unless user.admin || user.in?(course.editors)
return course.title
end
+
link_to(course.title, edit_course_path(course))
end
@@ -40,5 +41,4 @@ def course_edit_icon(course)
tag.i class: 'far fa-edit'
end
end
-
end
diff --git a/app/helpers/items_helper.rb b/app/helpers/items_helper.rb
index 2bb92a957..217a5c6cc 100644
--- a/app/helpers/items_helper.rb
+++ b/app/helpers/items_helper.rb
@@ -17,6 +17,7 @@ def select_script_items(lecture)
def check_unless_hidden(item_id)
return 'checked' unless Item.find_by_id(item_id)&.hidden
+
''
end
diff --git a/app/helpers/lectures_helper.rb b/app/helpers/lectures_helper.rb
index 3123e56c8..c64225e9a 100644
--- a/app/helpers/lectures_helper.rb
+++ b/app/helpers/lectures_helper.rb
@@ -41,24 +41,28 @@ def days_short
# unpublished lecture get a different link color
def lectures_color(lecture)
return '' if lecture.published?
+
'unpublished'
end
# hidden chapters get a different color
def chapter_card_color(chapter)
return 'bg-mdb-color-lighten-5' unless chapter.hidden
+
'greyed_out bg-grey'
end
# hidden chapters get a different header color
def chapter_header_color(chapter)
return 'bg-mdb-color-lighten-2' unless chapter.hidden
+
''
end
# hidden sections get a different color
def section_color(section)
return '' unless section.hidden
+
'greyed_out'
end
@@ -67,36 +71,42 @@ def section_background_color(section)
unless !section.chapter.hidden && section.hidden
return 'bg-mdb-color-lighten-6'
end
+
'bg-grey'
end
def news_color(news_count)
return '' unless news_count.positive?
+
'text-primary'
end
def lecture_header_color(subscribed, lecture)
return '' unless subscribed
+
result = 'text-light '
result += if lecture.term
- 'bg-mdb-color-lighten-1'
- else
- 'bg-info'
- end
+ 'bg-mdb-color-lighten-1'
+ else
+ 'bg-info'
+ end
end
def circle_icon(subscribed)
return 'fas fa-check-circle' if subscribed
+
'far fa-circle'
end
def lecture_border(lecture)
return '' if lecture.published?
+
'border-danger'
end
def lecture_access_icon(lecture)
return lecture_edit_icon if current_user.can_edit?(lecture)
+
lecture_view_icon
end
diff --git a/app/helpers/lessons_helper.rb b/app/helpers/lessons_helper.rb
index 0f2e016d8..0653e9207 100644
--- a/app/helpers/lessons_helper.rb
+++ b/app/helpers/lessons_helper.rb
@@ -10,6 +10,7 @@ def lesson_tag_selection(lesson)
def edit_or_show_lesson_path(lesson)
return edit_lesson_path(lesson) if current_user.can_edit?(lesson.lecture)
+
lesson_path(lesson)
end
end
diff --git a/app/helpers/media_helper.rb b/app/helpers/media_helper.rb
index 317c9eed6..a95385e85 100644
--- a/app/helpers/media_helper.rb
+++ b/app/helpers/media_helper.rb
@@ -32,6 +32,7 @@ def inspect_or_edit_medium_path(medium, inspection)
# create text for notification about new medium in notification dropdown menu
def medium_notification_item_header(medium)
return unless medium.proper?
+
t('notifications.new_medium_in') + medium.scoped_teachable_title
end
@@ -45,6 +46,7 @@ def medium_notification_card_header(medium)
if teachable.media_scope.class.to_s == 'Course'
return teachable.media_scope.title_for_viewers
end
+
link_to(teachable.media_scope.title_for_viewers,
medium.teachable.media_scope.path(current_user),
class: 'text-dark')
@@ -63,14 +65,15 @@ def section_selection(medium)
def preselected_sections(medium)
return [] unless medium.teachable.class.to_s == 'Lesson'
+
medium.teachable.sections.map(&:id)
end
-
def textcolor(medium)
return '' if medium.visible?
return 'locked' if medium.locked?
return 'scheduled_release' if medium.publisher.present?
+
'unpublished'
end
@@ -78,6 +81,7 @@ def infotainment(medium)
return 'nichts' unless medium.video || medium.manuscript
return 'ein Video' unless medium.manuscript
return 'ein Manuskript' unless medium.video
+
'ein Video und ein Manuskript'
end
@@ -85,16 +89,19 @@ def level_to_word(medium)
return t('basics.not_set') unless medium.level.present?
return t('basics.level_easy') if medium.level == 0
return t('basics.level_medium') if medium.level == 1
+
t('basics.level_hard')
end
def independent_to_word(medium)
return t('basics.no_lc') unless medium.independent
+
t('basics.yes_lc')
end
def medium_border(medium)
return if medium.published? && !medium.locked?
+
'border-danger'
end
@@ -103,17 +110,19 @@ def media_sorts_select(purpose)
return Medium.select_question if purpose == 'clicker'
return add_prompt(Medium.select_importables) if purpose == 'import'
return add_prompt(Medium.select_generic) if !current_user.admin?
+
add_prompt(Medium.select_sorts)
end
def sort_preselect(purpose)
return '' unless purpose == 'quiz'
+
'Question'
end
def related_media_hash(references, media)
media_list = references.map { |r| [r.medium, r.manuscript_link] } +
- media.zip(Array.new(media.size))
+ media.zip(Array.new(media.size))
hash = {}
Medium.sort_enum.each do |s|
media_in_s = media_list.select { |m| m.first.sort == s }
@@ -124,6 +133,7 @@ def related_media_hash(references, media)
def release_date_info(medium)
return unless medium.publisher.present?
+
t('admin.medium.scheduled_for_release_short',
release_date: I18n.l(medium.publisher&.release_date,
format: :long,
@@ -132,6 +142,7 @@ def release_date_info(medium)
def edit_or_show_medium_path(medium)
return edit_medium_path(medium) if current_user.can_edit?(medium)
+
medium_path(medium)
end
diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb
index 8096b8447..74ff9883c 100644
--- a/app/helpers/notifications_helper.rb
+++ b/app/helpers/notifications_helper.rb
@@ -7,6 +7,7 @@ def notification_menu_item_header(notification)
return medium_notification_item_header(notifiable) if notification.medium?
return course_notification_item_header(notifiable) if notification.course?
return lecture_notification_item_header(notifiable) if notification.lecture?
+
announcement_notification_item_header(notifiable)
end
@@ -18,6 +19,7 @@ def notification_menu_item_details(notification)
if notification.lecture?
return lecture_notification_item_details(notifiable)
end
+
''
end
@@ -26,6 +28,7 @@ def notification_color(notification)
return 'bg-post-it-blue' if notification.generic_announcement?
return 'bg-post-it-red' if notification.announcement?
return 'bg-post-it-orange' if notification.course? || notification.lecture?
+
'bg-post-it-yellow'
end
@@ -33,14 +36,14 @@ def notification_color(notification)
def notification_header(notification)
notifiable = notification.notifiable
text = if notification.medium?
- medium_notification_card_header(notifiable)
- elsif notification.course? || notification.lecture?
- t('notifications.course_selection')
- elsif notification.lecture_announcement?
- announcement_notification_card_header(notifiable)
- else
- link_to t('mampf_news.title'), news_path, class: 'text-dark'
- end
+ medium_notification_card_header(notifiable)
+ elsif notification.course? || notification.lecture?
+ t('notifications.course_selection')
+ elsif notification.lecture_announcement?
+ announcement_notification_card_header(notifiable)
+ else
+ link_to t('mampf_news.title'), news_path, class: 'text-dark'
+ end
text.html_safe
end
@@ -48,14 +51,14 @@ def notification_header(notification)
def notification_text(notification)
notifiable = notification.notifiable
text = if notification.medium?
- t('notifications.new_medium')
- elsif notification.course?
- course_notification_card_text(notifiable)
- elsif notification.lecture?
- lecture_notification_card_text(notifiable)
- else
- t('notifications.new_announcement')
- end
+ t('notifications.new_medium')
+ elsif notification.course?
+ course_notification_card_text(notifiable)
+ elsif notification.lecture?
+ lecture_notification_card_text(notifiable)
+ else
+ t('notifications.new_announcement')
+ end
text.html_safe
end
@@ -63,21 +66,23 @@ def notification_text(notification)
def notification_link(notification)
notifiable = notification.notifiable
return '' unless notifiable
+
text = if notification.medium?
- medium_notification_card_link(notifiable)
- elsif notification.course?
- course_notification_card_link
- elsif notification.lecture?
- lecture_notification_card_link
- else
- notifiable.details
- end
+ medium_notification_card_link(notifiable)
+ elsif notification.course?
+ course_notification_card_link
+ elsif notification.lecture?
+ lecture_notification_card_link
+ else
+ notifiable.details
+ end
text.html_safe
end
def items_card_size(small, comments_below)
return '30vh' if comments_below
return '60vh' if small
+
'70vh'
end
end
diff --git a/app/helpers/referrals_helper.rb b/app/helpers/referrals_helper.rb
index 14d80fda3..fe8eef939 100644
--- a/app/helpers/referrals_helper.rb
+++ b/app/helpers/referrals_helper.rb
@@ -9,16 +9,19 @@ def teachable_selector(referral)
return referral.medium.teachable&.media_scope&.selector_value
end
return 'external-0' if referral.item.sort == 'link'
+
referral.item.medium.teachable&.media_scope&.selector_value
end
def show_link(referral)
return true if referral.item.present? && referral.item.sort == 'link'
+
false
end
def show_explanation(referral)
return false if referral.item.nil?
+
true
end
@@ -28,15 +31,17 @@ def show_explanation(referral)
def item_status_color(referral)
return '' if referral.item.sort == 'link'
if !referral.item_published? || referral.item_locked? ||
- referral.item.quarantine
+ referral.item.quarantine
return 'bg-post-it-pink'
end
+
''
end
def item_status_color_value(referral)
return 'white' if referral.item.sort == 'link'
return '#fad1df' if !referral.item_published? || referral.item_locked?
+
'white'
end
end
diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb
index 91b5eea6c..e1e5d90c4 100644
--- a/app/helpers/search_helper.rb
+++ b/app/helpers/search_helper.rb
@@ -10,11 +10,13 @@ def plural_n(tags, filtered_tags)
def hits_per_page(results_as_list)
return [[10, 10], [20, 20], [50, 50]] if results_as_list
- [[3,3],[4,4],[6,6], [12,12]]
+
+ [[3, 3], [4, 4], [6, 6], [12, 12]]
end
def default_hits_per_page(results_as_list)
return 20 if results_as_list
+
6
end
end
diff --git a/app/helpers/submissions_helper.rb b/app/helpers/submissions_helper.rb
index 78b89e8f0..b44505b31 100644
--- a/app/helpers/submissions_helper.rb
+++ b/app/helpers/submissions_helper.rb
@@ -2,6 +2,7 @@
module SubmissionsHelper
def cancel_editing_submission_path(submission)
return cancel_edit_submission_path(submission) if submission.persisted?
+
cancel_new_submission_path(params: { assignment_id: submission.assignment.id })
end
@@ -14,49 +15,58 @@ def partner_preselection(user, lecture)
end
def admissible_invitee_selection(user, submission, lecture)
- submission.admissible_invitees(user).map { |u| [u.tutorial_name, u.id] }
+ submission.admissible_invitees(user).map { |u| [u.tutorial_name, u.id] }
end
def probable_invitee_ids(user, submission, lecture)
- partner_preselection(user, lecture) -
- (submission.users + submission.invited_users).map(&:id)
+ partner_preselection(user, lecture) -
+ (submission.users + submission.invited_users).map(&:id)
end
def invitations_possible?(submission, user)
- return false if submission.admissible_invitees(user).empty?
- return true unless submission.assignment.lecture.submission_max_team_size
- submission.users.size <
- submission.assignment.lecture.submission_max_team_size
+ return false if submission.admissible_invitees(user).empty?
+ return true unless submission.assignment.lecture.submission_max_team_size
+
+ submission.users.size <
+ submission.assignment.lecture.submission_max_team_size
end
def submission_color(submission, assignment)
- if assignment.active?
- return 'bg-submission-green' if submission&.manuscript
- return 'bg-submission-yellow' if submission
- return 'bg-submission-red'
- else
- return 'bg-submission-darker-green' if submission&.correction
+ if assignment.active?
+ return 'bg-submission-green' if submission&.manuscript
+ return 'bg-submission-yellow' if submission
+
+ return 'bg-submission-red'
+ else
+ return 'bg-submission-darker-green' if submission&.correction
+
if submission&.manuscript && submission.too_late?
return 'bg-submission-orange' if submission.accepted.nil?
return 'bg-submission-green' if submission.accepted
+
return 'bg-submission-red'
end
- return 'bg-submission-green' if submission&.manuscript
- return 'bg-submission-red'
- end
+ return 'bg-submission-green' if submission&.manuscript
+
+ return 'bg-submission-red'
+ end
end
def submission_status_icon(submission, assignment)
if assignment.active?
return 'far fa-smile' if submission&.manuscript
+
return 'fas fa-exclamation-triangle'
else
return 'far fa-smile' if submission&.correction
+
if submission&.manuscript && submission.too_late?
return 'fas fa-hourglass-start' if submission.accepted
+
return 'fas fa-exclamation-triangle'
end
return 'fas fa-hourglass-start' if submission&.manuscript
+
return 'fas fa-exclamation-triangle'
end
end
@@ -65,23 +75,27 @@ def submission_status_text(submission, assignment)
if assignment.active?
return t('submission.okay') if submission&.manuscript
return t('submission.no_file') if submission
+
return t('submission.nothing')
else
return t('submission.with_correction') if submission&.correction
+
if submission&.manuscript && submission.too_late?
return t('submission.too_late') if submission.accepted.nil?
return t('submission.too_late_accepted') if submission.accepted
+
return t('submission.too_late_rejected')
end
return t('submission.under_review') if submission&.manuscript
return t('submission.no_file') if submission
+
return t('submission.nothing')
end
end
def submission_status(submission, assignment)
tag.i class: [submission_status_icon(submission, assignment), 'fa-lg'],
- data: { toggle: 'tooltip'},
+ data: { toggle: 'tooltip' },
title: submission_status_text(submission, assignment)
end
@@ -89,25 +103,29 @@ def show_submission_footer?(submission, assignment)
return true if assignment.active?
return false if assignment.totally_expired?
return false if submission&.correction
+
true
end
def submission_late_color(submission)
return '' unless submission.too_late?
return '' unless submission.accepted.nil?
+
'bg-submission-orange'
end
def late_submission_info(submission, tutorial)
text = t('submission.late')
return text unless submission.accepted.nil? && current_user.in?(tutorial.tutors)
+
"#{text} (#{t('tutorial.late_submission_decision')})"
end
def correction_display_mode(submission)
- accepted = submission.assignment.accepted_file_type
- non_inline = Assignment.non_inline_file_types
- return t('buttons.show') unless accepted.in?(non_inline)
- t('buttons.download')
+ accepted = submission.assignment.accepted_file_type
+ non_inline = Assignment.non_inline_file_types
+ return t('buttons.show') unless accepted.in?(non_inline)
+
+ t('buttons.download')
end
-end
\ No newline at end of file
+end
diff --git a/app/helpers/talks_helper.rb b/app/helpers/talks_helper.rb
index be87e2625..3ef166bbf 100644
--- a/app/helpers/talks_helper.rb
+++ b/app/helpers/talks_helper.rb
@@ -7,16 +7,19 @@ def talk_positions_for_select(talk)
def talk_card_color(talk, user)
return 'bg-mdb-color-lighten-2' unless user.in?(talk.speakers)
+
'bg-info'
end
def speaker_list(talk)
return t('basics.tba') unless talk.speakers.present?
+
talk.speakers.map(&:tutorial_name).join(', ')
end
def speaker_icon_class(talk)
return 'fas fa-user' unless talk.speakers.count > 1
+
'fas fa-users'
end
@@ -39,4 +42,4 @@ def date_list(talk)
def cospeaker_list(talk, user)
(talk.speakers.to_a - [user]).map(&:tutorial_name).join(', ')
end
-end
\ No newline at end of file
+end
diff --git a/app/helpers/tutorials_helper.rb b/app/helpers/tutorials_helper.rb
index da7657c1d..7cb929bf7 100644
--- a/app/helpers/tutorials_helper.rb
+++ b/app/helpers/tutorials_helper.rb
@@ -2,16 +2,18 @@
module TutorialsHelper
def cancel_editing_tutorial_path(tutorial)
return cancel_edit_tutorial_path(tutorial) if tutorial.persisted?
+
cancel_new_tutorial_path(params: { lecture: tutorial.lecture })
end
def tutorial_preselection(tutorial)
return [[]] unless tutorial.persisted? && tutorial.tutors.any?
+
options_for_select(tutorial.tutors.map { |t| [t.tutorial_info, t.id] },
tutorial.tutor_ids)
end
def tutorials_selection(lecture)
- lecture.tutorials.map { |t| [t.title_with_tutors, t.id] }
+ lecture.tutorials.map { |t| [t.title_with_tutors, t.id] }
end
end
diff --git a/app/helpers/vertices_helper.rb b/app/helpers/vertices_helper.rb
index 5ce17d3dc..db0401c48 100644
--- a/app/helpers/vertices_helper.rb
+++ b/app/helpers/vertices_helper.rb
@@ -12,4 +12,4 @@ def vertices_labels(quiz, vertex_id, undefined)
def crosses_id(crosses)
crosses.keys.collect { |k| [k, crosses[k].to_s.first] }.flatten.join
end
-end
\ No newline at end of file
+end
diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb
index 13fdba3ff..d8255248e 100644
--- a/app/mailers/application_mailer.rb
+++ b/app/mailers/application_mailer.rb
@@ -1,6 +1,8 @@
class ApplicationMailer < ActionMailer::Base
helper EmailHelper
default from: DefaultSetting::PROJECT_EMAIL
- default "Message-ID" => -> {"<#{rand.to_s.split('.')[1]}.#{Time.now.to_i}@#{ENV['MAILID_DOMAIN']}>" }
+ default "Message-ID" => -> {
+ "<#{rand.to_s.split('.')[1]}.#{Time.now.to_i}@#{ENV['MAILID_DOMAIN']}>"
+ }
layout 'mailer'
end
diff --git a/app/mailers/exception_handler/exception_mailer.rb b/app/mailers/exception_handler/exception_mailer.rb
index dfe09b2aa..aa1913e52 100644
--- a/app/mailers/exception_handler/exception_mailer.rb
+++ b/app/mailers/exception_handler/exception_mailer.rb
@@ -1,6 +1,5 @@
module ExceptionHandler
class ExceptionMailer < ActionMailer::Base
-
# Layout
layout "exception_mailer"
@@ -17,4 +16,4 @@ def new_exception e
Rails.logger.info "Exception Sent To → #{ExceptionHandler.config.email}"
end
end
-end
\ No newline at end of file
+end
diff --git a/app/mailers/mathi_mailer.rb b/app/mailers/mathi_mailer.rb
index f55eeb203..438fbe30e 100644
--- a/app/mailers/mathi_mailer.rb
+++ b/app/mailers/mathi_mailer.rb
@@ -4,6 +4,7 @@ class MathiMailer < ApplicationMailer
def ghost_email(user)
return if user.ghost_hash.nil?
+
@name = user.name
@hash = user.ghost_hash
mail(to: user.email, subject: t('mailer.hash_mail_subject'))
@@ -17,7 +18,8 @@ def data_request_email(user)
def data_provide_email(user)
@user = user
- mail(to: user.email, subject: t('mailer.data_provide_mail_subject')) do |format|
+ mail(to: user.email,
+ subject: t('mailer.data_provide_mail_subject')) do |format|
format.html { render layout: 'mailer' }
end
end
diff --git a/app/mailers/my_mailer.rb b/app/mailers/my_mailer.rb
index 160ad930e..c57e0eb04 100644
--- a/app/mailers/my_mailer.rb
+++ b/app/mailers/my_mailer.rb
@@ -4,6 +4,8 @@ class MyMailer < Devise::Mailer
layout "devise_mailer"
default template_path: 'devise/mailer' # to make sure that your mailer uses the devise views
default from: DefaultSetting::PROJECT_EMAIL
- default "Message-ID" => -> {"<#{rand.to_s.split('.')[1]}.#{Time.now.to_i}@#{ENV['MAILID_DOMAIN']}>" }
+ default "Message-ID" => -> {
+ "<#{rand.to_s.split('.')[1]}.#{Time.now.to_i}@#{ENV['MAILID_DOMAIN']}>"
+ }
helper EmailHelper
end
diff --git a/app/mailers/notification_mailer.rb b/app/mailers/notification_mailer.rb
index 3f8d6eab4..03a4419b0 100644
--- a/app/mailers/notification_mailer.rb
+++ b/app/mailers/notification_mailer.rb
@@ -22,7 +22,6 @@ class NotificationMailer < ApplicationMailer
only: [:submission_join_email,
:submission_leave_email]
-
def medium_email
@medium = params[:medium]
mail(from: @sender,
@@ -34,11 +33,11 @@ def medium_email
def announcement_email
@announcement = params[:announcement]
@announcement_details = if @announcement.lecture.present?
- t('in') + ' ' +
- @announcement.lecture.title_for_viewers
- else
- t('mailer.mampf_news')
- end
+ t('in') + ' ' +
+ @announcement.lecture.title_for_viewers
+ else
+ t('mailer.mampf_news')
+ end
mail(from: @sender,
bcc: @recipients.pluck(:email),
subject: t('mailer.announcement_subject') + ' ' +
@@ -50,9 +49,9 @@ def new_lecture_email
mail(from: @sender,
bcc: @recipients.pluck(:email),
subject: t('mailer.new_lecture_subject',
- title: @lecture.title_for_viewers))
+ title: @lecture.title_for_viewers))
end
-
+
def new_editor_email
@lecture = params[:lecture]
@recipient = params[:recipient]
@@ -61,9 +60,9 @@ def new_editor_email
mail(from: @sender,
to: @recipient.email,
subject: t('mailer.new_editor_subject',
- title: @lecture.title_for_viewers))
+ title: @lecture.title_for_viewers))
end
-
+
def submission_invitation_email
@recipient = params[:recipient]
@assignment = params[:assignment]
@@ -177,26 +176,26 @@ def submission_destruction_lecture_email
private
- def set_sender_and_locale
- @sender = "#{t('mailer.notification')} <#{DefaultSetting::PROJECT_NOTIFICATION_EMAIL}>"
- I18n.locale = params[:locale]
- end
+ def set_sender_and_locale
+ @sender = "#{t('mailer.notification')} <#{DefaultSetting::PROJECT_NOTIFICATION_EMAIL}>"
+ I18n.locale = params[:locale]
+ end
- def set_recipients
- @recipients = User.where(id: params[:recipients])
- end
+ def set_recipients
+ @recipients = User.where(id: params[:recipients])
+ end
- def set_recipient_and_submission
- @recipient = params[:recipient]
- @submission = params[:submission]
- @assignment = @submission.assignment
- end
+ def set_recipient_and_submission
+ @recipient = params[:recipient]
+ @submission = params[:submission]
+ @assignment = @submission.assignment
+ end
- def set_filename
- @filename = params[:filename]
- end
+ def set_filename
+ @filename = params[:filename]
+ end
- def set_user
- @user = params[:user]
- end
+ def set_user
+ @user = params[:user]
+ end
end
diff --git a/app/models/ability.rb b/app/models/ability.rb
index b96221856..fbf76c958 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -8,4 +8,4 @@ class Ability
def initialize(user)
end
-end
\ No newline at end of file
+end
diff --git a/app/models/announcement.rb b/app/models/announcement.rb
index 43d7bc56e..04d8eae44 100644
--- a/app/models/announcement.rb
+++ b/app/models/announcement.rb
@@ -8,7 +8,7 @@ class Announcement < ApplicationRecord
paginates_per 10
- scope :active_on_main, -> { where(on_main_page: true, lecture:nil) }
+ scope :active_on_main, -> { where(on_main_page: true, lecture: nil) }
# does there (still) exist a notification for the announcement for
# the given user
diff --git a/app/models/answer.rb b/app/models/answer.rb
index 4af1f90cf..7bc2403a1 100644
--- a/app/models/answer.rb
+++ b/app/models/answer.rb
@@ -12,6 +12,7 @@ def conditional_explanation(correct)
unless correct
return explanation.string_between_markers(':(inkorrekt:', ')')
end
+
explanation.string_between_markers('(korrekt:', '):')
end
@@ -26,24 +27,24 @@ def text_join
private
- def question_not_orphaned?
- throw(:abort) if question.answers.size == 1
- true
- end
+ def question_not_orphaned?
+ throw(:abort) if question.answers.size == 1
+ true
+ end
- def update_quizzes
- question.quiz_ids.each do |q|
- quiz = Quiz.find(q)
- quiz_graph = quiz.quiz_graph
- vertices = quiz_graph.find_vertices(question)
- vertices.each do |v|
- quiz_graph.reset_vertex_answers_change(v)
+ def update_quizzes
+ question.quiz_ids.each do |q|
+ quiz = Quiz.find(q)
+ quiz_graph = quiz.quiz_graph
+ vertices = quiz_graph.find_vertices(question)
+ vertices.each do |v|
+ quiz_graph.reset_vertex_answers_change(v)
+ end
+ quiz.update(quiz_graph: quiz_graph)
end
- quiz.update(quiz_graph: quiz_graph)
end
- end
- def touch_medium
- question.becomes(Medium).update(updated_at: Time.now)
- end
+ def touch_medium
+ question.becomes(Medium).update(updated_at: Time.now)
+ end
end
diff --git a/app/models/assignment.rb b/app/models/assignment.rb
index 6ad38bdb6..0da21a6ad 100644
--- a/app/models/assignment.rb
+++ b/app/models/assignment.rb
@@ -30,9 +30,9 @@ def self.accepted_file_types
inclusion: { in: Assignment.accepted_file_types }
def submission(user)
- UserSubmissionJoin.where(submission: Submission.where(assignment: self),
- user: user)
- &.first&.submission
+ UserSubmissionJoin.where(submission: Submission.where(assignment: self),
+ user: user)
+ &.first&.submission
end
def submitter_ids
@@ -52,7 +52,7 @@ def semiactive?
end
def expired?
- !active?
+ !active?
end
def totally_expired?
@@ -65,27 +65,30 @@ def in_grace_period?
def friendly_deadline
return deadline unless lecture.submission_grace_period
+
deadline + lecture.submission_grace_period.minutes
end
def current?
- self.in?(lecture.current_assignments)
+ self.in?(lecture.current_assignments)
end
def previous?
- self.in?(lecture.previous_assignments)
+ self.in?(lecture.previous_assignments)
end
def previous
siblings = lecture.assignments_by_deadline
position = siblings.map(&:first).find_index(deadline)
return unless position.positive?
+
siblings[position - 1].second
end
def submission_partners(user)
submission = submission(user)
return unless submission
+
submission.users - [user]
end
@@ -94,16 +97,17 @@ def tutorial(user)
end
def destructible?
- submissions.proper.none?
+ submissions.proper.none?
end
def check_destructibility
- throw(:abort) unless destructible?
- true
+ throw(:abort) unless destructible?
+ true
end
def has_documents?
return false unless medium
+
medium.video || medium.manuscript || medium.geogebra ||
medium.external_reference_link.present? ||
(medium.sort == 'Quiz' && medium.quiz_graph)
@@ -141,12 +145,12 @@ def accepted_mime_types
# is set to .tar.gz
# see e.g. https://bugs.chromium.org/p/chromium/issues/detail?id=521781
def accepted_for_file_input
- return accepted_file_type unless accepted_file_type == '.tar.gz'
- '.gz'
+ return accepted_file_type unless accepted_file_type == '.tar.gz'
+
+ '.gz'
end
def localized_deletion_date
deletion_date.strftime(I18n.t('date.formats.concise'))
end
-
end
diff --git a/app/models/chapter.rb b/app/models/chapter.rb
index 6841ff5e3..cad5d882c 100644
--- a/app/models/chapter.rb
+++ b/app/models/chapter.rb
@@ -16,13 +16,15 @@ def to_label
number: displayed_number,
title: title)
end
- I18n.t("hidden_#{lecture.chapter_name}", number: displayed_number, title: title)
+ I18n.t("hidden_#{lecture.chapter_name}", number: displayed_number,
+ title: title)
end
# Returns the number of the chapter. Unless the user explicitly specified
# a display number, this number is calculated
def displayed_number
return calculated_number unless display_number.present?
+
display_number
end
@@ -35,6 +37,7 @@ def reference
# Returns the chapter number based on the position in the chapters list.
def calculated_number
return position.to_s unless lecture.start_chapter.present?
+
(lecture.start_chapter + position - 1).to_s
end
diff --git a/app/models/clicker.rb b/app/models/clicker.rb
index 13742f271..075918d04 100644
--- a/app/models/clicker.rb
+++ b/app/models/clicker.rb
@@ -36,14 +36,15 @@ def close!
def results
total = votes.count
return unless total.positive?
+
(1..alternatives).map { |i| votes.where(value: i).count / total.to_f }
.map { |x| (100 * x).round }
end
private
- def set_basics
- self.code = SecureRandom.uuid
- self.alternatives = 3
- end
+ def set_basics
+ self.code = SecureRandom.uuid
+ self.alternatives = 3
+ end
end
diff --git a/app/models/clicker_vote.rb b/app/models/clicker_vote.rb
index 6c6a06046..8d73c024c 100644
--- a/app/models/clicker_vote.rb
+++ b/app/models/clicker_vote.rb
@@ -7,14 +7,15 @@ class ClickerVote < ApplicationRecord
private
- def clicker_open
- return true if clicker.open?
- errors.add(:clicker, :clicker_closed)
- end
+ def clicker_open
+ return true if clicker.open?
- def value_in_range
- return true if value.in?(1..clicker.alternatives)
- errors.add(:value, :out_of_range)
- end
-end
+ errors.add(:clicker, :clicker_closed)
+ end
+
+ def value_in_range
+ return true if value.in?(1..clicker.alternatives)
+ errors.add(:value, :out_of_range)
+ end
+end
diff --git a/app/models/course_self_join.rb b/app/models/course_self_join.rb
index 0353e1c48..7311f85eb 100644
--- a/app/models/course_self_join.rb
+++ b/app/models/course_self_join.rb
@@ -5,14 +5,14 @@
class CourseSelfJoin < ApplicationRecord
belongs_to :course
belongs_to :preceding_course, class_name: 'Course'
- validates :preceding_course, uniqueness: { scope: :course}
+ validates :preceding_course, uniqueness: { scope: :course }
# we do not allow a course to be preceding itself
after_save :destroy, if: :self_inverse?
private
- def self_inverse?
- course_id == preceding_course_id
- end
+ def self_inverse?
+ course_id == preceding_course_id
+ end
end
diff --git a/app/models/course_tag_join.rb b/app/models/course_tag_join.rb
index d97f91449..92a30f4e2 100644
--- a/app/models/course_tag_join.rb
+++ b/app/models/course_tag_join.rb
@@ -12,8 +12,9 @@ class CourseTagJoin < ApplicationRecord
private
- def touch_tag
- return unless tag.present? && tag.persisted?
- tag.touch
- end
+ def touch_tag
+ return unless tag.present? && tag.persisted?
+
+ tag.touch
+ end
end
diff --git a/app/models/division.rb b/app/models/division.rb
index 148b5b9c6..bab3b37ce 100644
--- a/app/models/division.rb
+++ b/app/models/division.rb
@@ -3,12 +3,12 @@ class Division < ApplicationRecord
has_many :division_course_joins
has_many :courses, through: :division_course_joins
- translates :name
+ translates :name
- globalize_accessors locales: I18n.available_locales,
- attributes: translated_attribute_names
+ globalize_accessors locales: I18n.available_locales,
+ attributes: translated_attribute_names
- def name_with_program
- "#{program.subject.name}:#{program.name}:#{name}"
- end
+ def name_with_program
+ "#{program.subject.name}:#{program.name}:#{name}"
+ end
end
diff --git a/app/models/interaction.rb b/app/models/interaction.rb
index 652ea675b..774e8e794 100644
--- a/app/models/interaction.rb
+++ b/app/models/interaction.rb
@@ -1,17 +1,19 @@
class Interaction < InteractionsRecord
-
- scope :created_between, lambda {|start_date, end_date| where(created_at: start_date.beginning_of_day..end_date.end_of_day)}
+ scope :created_between, lambda { |start_date, end_date|
+ where(created_at: start_date.beginning_of_day..end_date.end_of_day)
+ }
require 'csv'
def self.to_csv
- attributes = %w{id session_id created_at full_path referrer_url study_participant}
+ attributes = %w{id session_id created_at full_path referrer_url
+ study_participant}
CSV.generate(headers: true) do |csv|
csv << attributes
all.each do |interaction|
- csv << attributes.map{ |attr| interaction.send(attr) }
+ csv << attributes.map { |attr| interaction.send(attr) }
end
end
end
-end
\ No newline at end of file
+end
diff --git a/app/models/interactions_record.rb b/app/models/interactions_record.rb
index d832e6d7b..77ae77892 100644
--- a/app/models/interactions_record.rb
+++ b/app/models/interactions_record.rb
@@ -2,4 +2,4 @@ class InteractionsRecord < ApplicationRecord
self.abstract_class = true
connects_to database: { writing: :interactions, reading: :interactions }
-end
\ No newline at end of file
+end
diff --git a/app/models/item.rb b/app/models/item.rb
index ab01fce53..bef489836 100644
--- a/app/models/item.rb
+++ b/app/models/item.rb
@@ -62,6 +62,7 @@ class Item < ApplicationRecord
def end_time
return unless video?
return TimeStamp.new(total_seconds: medium.video_duration) if next_item.nil?
+
TimeStamp.new(total_seconds: next_item.start_time.total_seconds - 0.001)
end
@@ -79,6 +80,7 @@ def vtt_time_span
def vtt_text
return '' if sort == 'pdf_destination'
return description if sort == 'link'
+
short_description
end
@@ -88,6 +90,7 @@ def vtt_text
# "Bem. 29.13: zu freien Moduln\n\n"
def vtt_reference
return short_description + "\n\n" unless short_reference.present?
+
short_reference + ': ' + short_description + "\n\n"
end
@@ -97,6 +100,7 @@ def vtt_reference
# "Verweis auf LA 2 SS 17, Bem. 29.13:"
def vtt_meta_reference(referring_medium)
return I18n.t('item.external_reference') if sort == 'link'
+
ref = local?(referring_medium) ? short_reference : long_reference
I18n.t('item.internal_reference', ref: ref)
end
@@ -106,6 +110,7 @@ def vtt_meta_reference(referring_medium)
# "Bem. 29.13"
def short_reference
return math_reference if math_items.include?(sort)
+
toc_reference
end
@@ -116,6 +121,7 @@ def long_reference
return short_reference if sort.in?(['self', 'link'])
return short_ref_with_teachable if section.present?
return medium.title_for_viewers unless short_reference.present?
+
medium.title_for_viewers + ', ' + short_reference
end
@@ -124,6 +130,7 @@ def long_reference
def short_description
return section.title if sort == 'section' && section.present?
return medium.title_for_viewers if sort == 'self'
+
description.to_s
end
@@ -136,6 +143,7 @@ def short_description
def local_reference
unless sort.in?(['self', 'link', 'pdf_destination'])
return short_ref_with_description unless medium&.sort == 'Script'
+
return 'Skript, ' + short_ref_with_description
end
local_non_math_reference
@@ -148,6 +156,7 @@ def title_within_course
return '' unless medium.present? && medium.proper?
return local_reference if medium.teachable_type == 'Course'
return local_reference unless medium.teachable.media_scope.term
+
medium.teachable.media_scope.term.to_label_short + ', ' + local_reference
end
@@ -165,23 +174,26 @@ def title_within_lecture
# lesson's lecture
def local?(referring_medium)
return false unless section.present?
+
in?(referring_medium.teachable.lecture&.items.to_a)
end
# background color of different item sorts within thyme editor
def background
return '#70db70;' if ['remark', 'theorem', 'lemma', 'corollary',
- 'algorithm', 'Theorem', 'Corollary', 'Lemma',
- 'proposition'].include?(sort)
+ 'algorithm', 'Theorem', 'Corollary', 'Lemma',
+ 'proposition'].include?(sort)
return '#75d7f0;' if ['definition', 'annotation', 'example',
'figure', 'exercise', 'equation'].include?(sort)
return 'lightgray;' if sort == 'link' || sort == 'self'
+
''
end
# special background for sections
def section_background
return 'beige;' if sort == 'section'
+
'aliceblue;'
end
@@ -193,6 +205,7 @@ def video_link
return if sort == 'pdf_destination'
return unless video?
return video_link_untimed if sort == 'self'
+
video_link_timed
end
@@ -206,23 +219,25 @@ def manuscript_link
return unless manuscript?
return manuscript_link_destination if pdf_destination.present?
return manuscript_link_page if page.present?
+
manuscript_link_generic
end
def quiz_link
return unless quiz?
+
return quiz_link_generic
end
-
# if the associated medium contains an external link, it is returned
def medium_link
return unless medium_link?
+
medium.external_reference_link
end
def self.available_sorts
- ['definition','remark', 'lemma', 'theorem', 'example', 'annotation',
+ ['definition', 'remark', 'lemma', 'theorem', 'example', 'annotation',
'algorithm', 'corollary', 'section', 'label', 'subsection', 'Theorem',
'proposition', 'Lemma', 'Corollary', 'figure', 'chapter', 'exercise',
'equation']
@@ -285,190 +300,205 @@ def related_items_visible?
private
- def math_items
- ['remark', 'theorem', 'lemma', 'definition', 'annotation', 'example',
- 'corollary', 'algorithm', 'Theorem', 'proposition', 'Lemma', 'Corollary',
- 'figure', 'subsection', 'exercise', 'equation']
- end
+ def math_items
+ ['remark', 'theorem', 'lemma', 'definition', 'annotation', 'example',
+ 'corollary', 'algorithm', 'Theorem', 'proposition', 'Lemma', 'Corollary',
+ 'figure', 'subsection', 'exercise', 'equation']
+ end
- def other_items
- ['section', 'self', 'link', 'label', 'pdf_destination', 'chapter']
- end
+ def other_items
+ ['section', 'self', 'link', 'label', 'pdf_destination', 'chapter']
+ end
- def proper_link?
- sort == 'link' && link.present?
- end
+ def proper_link?
+ sort == 'link' && link.present?
+ end
- def next_item
- medium.proper_items_by_time.find do |i|
- i.start_time.total_seconds > start_time.total_seconds
+ def next_item
+ medium.proper_items_by_time.find do |i|
+ i.start_time.total_seconds > start_time.total_seconds
+ end
end
- end
- def sort_long
- I18n.t("admin.item.sort_short.#{sort}")
- end
+ def sort_long
+ I18n.t("admin.item.sort_short.#{sort}")
+ end
- # the next methods are used to put together the references and descriptions
+ # the next methods are used to put together the references and descriptions
- def math_item_number
- ref_number.to_s
- end
+ def math_item_number
+ ref_number.to_s
+ end
- def math_reference
- sort_long + ' ' + math_item_number
- end
+ def math_reference
+ sort_long + ' ' + math_item_number
+ end
- def special_reference
- return 'Medium' if sort == 'self'
- return '' if sort == 'pdf_destination'
- 'extern'
- end
+ def special_reference
+ return 'Medium' if sort == 'self'
+ return '' if sort == 'pdf_destination'
- def section_reference
- return section.displayed_number.to_s if section.present?
- return '§' + ref_number if ref_number.present?
- ''
- end
+ 'extern'
+ end
- def chapter_reference
- chapter_short = I18n.t('admin.item.chapter_short',
- locale: locale)
- return "#{chapter_short} #{ref_number}" if ref_number.present?
- chapter_short
- end
+ def section_reference
+ return section.displayed_number.to_s if section.present?
+ return '§' + ref_number if ref_number.present?
- def toc_reference
- return section_reference if sort == 'section'
- return chapter_reference if sort == 'chapter'
- if sort == 'label'
- return '' if description.present?
- return 'destination: ' + pdf_destination.to_s
+ ''
end
- special_reference
- end
- def non_math_reference
- return medium.title_for_viewers if sort == 'self'
- if sort == 'pdf_destination'
- return medium.title_for_viewers + ' (pdf) # ' + description
+ def chapter_reference
+ chapter_short = I18n.t('admin.item.chapter_short',
+ locale: locale)
+ return "#{chapter_short} #{ref_number}" if ref_number.present?
+
+ chapter_short
end
- 'extern ' + description.to_s if sort == 'link'
- end
- def local_non_math_reference
- return medium.local_title_for_viewers if sort == 'self'
- if sort == 'pdf_destination'
- return medium.local_title_for_viewers + ' (pdf) # ' + description
+ def toc_reference
+ return section_reference if sort == 'section'
+ return chapter_reference if sort == 'chapter'
+
+ if sort == 'label'
+ return '' if description.present?
+
+ return 'destination: ' + pdf_destination.to_s
+ end
+ special_reference
end
- 'extern ' + description.to_s if sort == 'link'
- end
- def short_ref_with_teachable
- unless short_reference.present?
- return medium.teachable.lecture.title_for_viewers
+ def non_math_reference
+ return medium.title_for_viewers if sort == 'self'
+ if sort == 'pdf_destination'
+ return medium.title_for_viewers + ' (pdf) # ' + description
+ end
+
+ 'extern ' + description.to_s if sort == 'link'
end
- medium.teachable.lecture.title_for_viewers + ', ' + short_reference
- end
- def short_ref_with_description
- return short_reference + ' ' + description.to_s unless sort == 'section'
- short_ref_for_sections
- end
+ def local_non_math_reference
+ return medium.local_title_for_viewers if sort == 'self'
+ if sort == 'pdf_destination'
+ return medium.local_title_for_viewers + ' (pdf) # ' + description
+ end
- def short_ref_for_sections
- return short_reference + ' ' + description if description.present?
- return short_reference + ' ' + section.title if section.present?
- short_reference
- end
+ 'extern ' + description.to_s if sort == 'link'
+ end
- # the next two methods get video links using helper methods
+ def short_ref_with_teachable
+ unless short_reference.present?
+ return medium.teachable.lecture.title_for_viewers
+ end
- def video_link_untimed
- Rails.application.routes.url_helpers.play_medium_path(medium.id)
- end
+ medium.teachable.lecture.title_for_viewers + ', ' + short_reference
+ end
- def video_link_timed
- Rails.application.routes.url_helpers
- .play_medium_path(medium.id, time: start_time.total_seconds)
- end
+ def short_ref_with_description
+ return short_reference + ' ' + description.to_s unless sort == 'section'
- def manuscript_link_generic
- Rails.application.routes.url_helpers.display_medium_path(medium.id)
- end
+ short_ref_for_sections
+ end
- def manuscript_link_destination
- Rails.application.routes.url_helpers
- .display_medium_path(medium.id, destination: pdf_destination)
- end
+ def short_ref_for_sections
+ return short_reference + ' ' + description if description.present?
+ return short_reference + ' ' + section.title if section.present?
- def manuscript_link_page
- Rails.application.routes.url_helpers
- .display_medium_path(medium.id, page: page)
- end
+ short_reference
+ end
- def quiz_link_generic
- Rails.application.routes.url_helpers.take_quiz_path(medium.id)
- end
+ # the next two methods get video links using helper methods
- # the next methods are used for validations
+ def video_link_untimed
+ Rails.application.routes.url_helpers.play_medium_path(medium.id)
+ end
- def valid_start_time
- return true if start_time.nil?
- return true if start_time.valid?
- errors.add(:start_time, :invalid_format)
- false
- end
+ def video_link_timed
+ Rails.application.routes.url_helpers
+ .play_medium_path(medium.id, time: start_time.total_seconds)
+ end
- def start_time_not_required
- medium.nil? || medium.sort == 'Script' || sort == 'self' ||
- sort == 'pdf_destination' || !start_time&.valid? || !medium.video
- end
+ def manuscript_link_generic
+ Rails.application.routes.url_helpers.display_medium_path(medium.id)
+ end
- def start_time_not_too_late
- return true if start_time_not_required
- return true if start_time.total_seconds <= medium.video.metadata['duration']
- errors.add(:start_time, :too_late)
- false
- end
+ def manuscript_link_destination
+ Rails.application.routes.url_helpers
+ .display_medium_path(medium.id, destination: pdf_destination)
+ end
- def start_times_without
- (medium.proper_items - [self]).map do |i|
- [i.start_time.floor_seconds, i.start_time.milliseconds]
+ def manuscript_link_page
+ Rails.application.routes.url_helpers
+ .display_medium_path(medium.id, page: page)
end
- end
- def no_duplicate_start_time
- return true if start_time_not_required
- if start_times_without.include?([start_time.floor_seconds,
- start_time.milliseconds])
- errors.add(:start_time, :taken)
+ def quiz_link_generic
+ Rails.application.routes.url_helpers.take_quiz_path(medium.id)
+ end
+
+ # the next methods are used for validations
+
+ def valid_start_time
+ return true if start_time.nil?
+ return true if start_time.valid?
+
+ errors.add(:start_time, :invalid_format)
false
end
- true
- end
- def nonempty_link_or_explanation
- return true if sort != 'link'
- return true if link.present?
- return true if explanation.present?
- errors.add(:link, :blank)
- errors.add(:explanation, :blank)
- end
+ def start_time_not_required
+ medium.nil? || medium.sort == 'Script' || sort == 'self' ||
+ sort == 'pdf_destination' || !start_time&.valid? || !medium.video
+ end
- # is used for after save and before destroy callbacks
- def touch_medium
- return unless medium.present? && medium.persisted?
- medium.touch
- end
+ def start_time_not_too_late
+ return true if start_time_not_required
+ return true if start_time.total_seconds <= medium.video.metadata['duration']
- # simulates the after_destroy callback for item_self_joins
- def destroy_joins(related_item)
- ItemSelfJoin.where(item: [self, related_item],
- related_item: [self, related_item]).delete_all
- end
+ errors.add(:start_time, :too_late)
+ false
+ end
- def locale
- medium&.locale || I18n.default_locale
- end
+ def start_times_without
+ (medium.proper_items - [self]).map do |i|
+ [i.start_time.floor_seconds, i.start_time.milliseconds]
+ end
+ end
+
+ def no_duplicate_start_time
+ return true if start_time_not_required
+
+ if start_times_without.include?([start_time.floor_seconds,
+ start_time.milliseconds])
+ errors.add(:start_time, :taken)
+ false
+ end
+ true
+ end
+
+ def nonempty_link_or_explanation
+ return true if sort != 'link'
+ return true if link.present?
+ return true if explanation.present?
+
+ errors.add(:link, :blank)
+ errors.add(:explanation, :blank)
+ end
+
+ # is used for after save and before destroy callbacks
+ def touch_medium
+ return unless medium.present? && medium.persisted?
+
+ medium.touch
+ end
+
+ # simulates the after_destroy callback for item_self_joins
+ def destroy_joins(related_item)
+ ItemSelfJoin.where(item: [self, related_item],
+ related_item: [self, related_item]).delete_all
+ end
+
+ def locale
+ medium&.locale || I18n.default_locale
+ end
end
diff --git a/app/models/item_self_join.rb b/app/models/item_self_join.rb
index be448bacc..8f03219d2 100644
--- a/app/models/item_self_join.rb
+++ b/app/models/item_self_join.rb
@@ -16,32 +16,33 @@ class ItemSelfJoin < ApplicationRecord
private
- def create_inverse
- self.class.create(inverse_relation_options)
- end
-
- def destroy_inverses
- inverses.destroy_all
- end
-
- def self_inverse?
- item_id == related_item_id
- end
-
- def inverse?
- self.class.exists?(inverse_relation_options) || self_inverse?
- end
-
- def inverses
- self.class.where(inverse_relation_options)
- end
-
- def inverse_relation_options
- { related_item_id: item_id, item_id: related_item_id }
- end
-
- def touch_item
- return if item.nil?
- item.touch
- end
+ def create_inverse
+ self.class.create(inverse_relation_options)
+ end
+
+ def destroy_inverses
+ inverses.destroy_all
+ end
+
+ def self_inverse?
+ item_id == related_item_id
+ end
+
+ def inverse?
+ self.class.exists?(inverse_relation_options) || self_inverse?
+ end
+
+ def inverses
+ self.class.where(inverse_relation_options)
+ end
+
+ def inverse_relation_options
+ { related_item_id: item_id, item_id: related_item_id }
+ end
+
+ def touch_item
+ return if item.nil?
+
+ item.touch
+ end
end
diff --git a/app/models/lecture.rb b/app/models/lecture.rb
index 4f510aecf..c8326b500 100644
--- a/app/models/lecture.rb
+++ b/app/models/lecture.rb
@@ -16,9 +16,9 @@ class Lecture < ApplicationRecord
# during the term, a lot of lessons take place for this lecture
has_many :lessons, -> { order(date: :asc, id: :asc) },
- dependent: :destroy,
- after_add: :touch_siblings,
- after_remove: :touch_siblings
+ dependent: :destroy,
+ after_add: :touch_siblings,
+ after_remove: :touch_siblings
# a lecture has many talks, which have positions
has_many :talks, -> { order(position: :asc) }, dependent: :destroy
@@ -37,7 +37,7 @@ class Lecture < ApplicationRecord
# a lecture has many users who have starred it (fans)
has_many :user_favorite_lecture_joins, dependent: :destroy
has_many :fans, -> { distinct }, through: :user_favorite_lecture_joins,
- source: :user
+ source: :user
# a lecture has many editors
# these are users different from the teacher who have the right to
@@ -84,7 +84,6 @@ class Lecture < ApplicationRecord
greater_than: -1 },
allow_nil: true
-
# as a teacher has editing rights by definition, we do not need him in the
# list of editors
after_save :remove_teacher_as_editor
@@ -161,11 +160,13 @@ def selector_value
def title
return course.title unless term
+
"(#{sort_localized_short}) #{course.title}, #{term.to_label}"
end
def title_no_term
return course.title unless term
+
"(#{sort_localized_short}) #{course.title}"
end
@@ -179,6 +180,7 @@ def to_label
def compact_title
return course.compact_title unless term
+
"#{sort_localized_short}.#{course.compact_title}.#{term.compact_title}"
end
@@ -202,6 +204,7 @@ def card_header
def card_header_path(user)
return unless user.lectures.include?(self)
+
lecture_path
end
@@ -218,6 +221,7 @@ def visible_for_user?(user)
return true if edited_by?(user)
return false unless published?
return false if restricted? && !self.in?(user.lectures)
+
true
end
@@ -276,6 +280,7 @@ def items
# and items in quarantine
def script_items_by_position
return [] unless manuscript
+
hidden_chapters = Chapter.where(hidden: true)
hidden_sections = Section.where(hidden: true)
.or(Section.where(chapter: hidden_chapters))
@@ -296,8 +301,8 @@ def manuscript
def media_with_inheritance_uncached
Medium.proper.where(teachable: self)
- .or(Medium.proper.where(teachable: self.lessons))
- .or(Medium.proper.where(teachable: self.talks))
+ .or(Medium.proper.where(teachable: self.lessons))
+ .or(Medium.proper.where(teachable: self.talks))
end
def media_with_inheritance_uncached_eagerload_stuff
@@ -307,7 +312,6 @@ def media_with_inheritance_uncached_eagerload_stuff
.proper.where(teachable: self.lessons + self.talks))
end
-
def media_with_inheritance
Rails.cache.fetch("#{cache_key_with_version}/media_with_inheritance") do
media_with_inheritance_uncached
@@ -363,32 +367,36 @@ def reste?(user)
project?('reste', user) || imported_any?('reste')
end
-
# the next methods put together some information on the lecture (teacher,
# term, title) in various combinations
def short_title
return course.short_title unless term
+
"(#{sort_localized_short}) #{course.short_title} #{term.to_label_short}"
end
def short_title_release
return short_title if published?
+
"#{short_title} (#{I18n.t('access.unpublished')})"
end
def short_title_brackets
return course.short_title unless term
+
"(#{sort_localized_short}) #{course.short_title} (#{term.to_label_short})"
end
def title_with_teacher
return title unless teacher.present? && teacher.name.present?
+
"#{title} (#{teacher.name})"
end
def title_with_teacher_no_type
return "#{course.title}, (#{teacher.name})" unless term
+
"#{course.title}, #{term.to_label} (#{teacher.name})"
end
@@ -396,11 +404,13 @@ def term_teacher_info
return term_to_label unless teacher.present?
return term_to_label unless teacher.name.present?
return "#{course.title}, #{teacher.name}" unless term
+
"(#{sort_localized_short}) #{term_to_label}, #{teacher.name}"
end
def term_teacher_published_info
return term_teacher_info if published?
+
"#{term_teacher_info} (#{I18n.t('access.unpublished')})"
end
@@ -410,11 +420,13 @@ def title_term_info
def title_term_info_no_type
return course.title unless term
+
"#{course.title}, #{term_to_label}"
end
def title_teacher_info
return course.title unless teacher.present? && teacher.name.present?
+
"(#{sort_localized_short}) #{course.title} (#{teacher.name})"
end
@@ -501,12 +513,14 @@ def editors_with_inheritance
def edited_by?(user)
return true if editors_with_inheritance.include?(user)
+
false
end
# returns path for show action of the lecture's course,
def path(user)
return unless user.lectures.include?(self)
+
Rails.application.routes.url_helpers
.lecture_path(self)
end
@@ -537,8 +551,8 @@ def lecture_lesson_results(filtered_media)
lecture_results +
lesson_results.includes(:teachable)
.sort_by do |m|
- [order_factor*m.lesson.date.jd,
- order_factor*m.lesson.id,
+ [order_factor * m.lesson.date.jd,
+ order_factor * m.lesson.id,
m.position]
end +
talk_results.includes(:teachable).sort_by do |m|
@@ -549,6 +563,7 @@ def lecture_lesson_results(filtered_media)
def order_factor
return -1 unless lecture.term.present?
return -1 if lecture.term.active
+
1
end
@@ -580,6 +595,7 @@ def forum
# by the user
def unread_forum_topics_count(user)
return unless forum?
+
forum_relation = Thredded::Messageboard.where(id: forum_id)
forum_view =
Thredded::MessageboardGroupView.grouped(forum_relation,
@@ -609,11 +625,13 @@ def self.select_sorts
def seminar?
return true if sort.in?(['seminar', 'proseminar', 'oberseminar'])
+
false
end
def chapter_name
return 'chapter' unless seminar?
+
'talk'
end
@@ -628,7 +646,7 @@ def close_comments!(user)
end
def open_comments!(user)
- media_with_inheritance.select { |m| m.commontator_thread.is_closed?}
+ media_with_inheritance.select { |m| m.commontator_thread.is_closed? }
.each { |m| m.commontator_thread.reopen }
end
@@ -640,10 +658,11 @@ def <=>(other)
return 0 if self == other
return 1 if self.begin_date < other.begin_date
return 1 if self.term == other.term &&
- ActiveSupport::Inflector.transliterate(self.course.title) >
- ActiveSupport::Inflector.transliterate(other.course.title)
+ ActiveSupport::Inflector.transliterate(self.course.title) >
+ ActiveSupport::Inflector.transliterate(other.course.title)
return 1 if self.term == other.term && self.course == other.course &&
- self.sort_localized < other.sort_localized
+ self.sort_localized < other.sort_localized
+
-1
end
@@ -652,10 +671,14 @@ def subscribed_by?(user)
end
def self.search_by(search_params, page)
- search_params[:types] = [] if search_params[:all_types] == '1' || search_params[:types].nil?
- search_params[:term_ids] = [] if search_params[:all_terms] == '1' || search_params[:term_ids].nil?
- search_params[:teacher_ids] = [] if search_params[:all_teachers] == '1' || search_params[:teacher_ids].nil?
- search_params[:program_ids] = [] if search_params[:all_programs] == '1' || search_params[:program_ids].nil?
+ search_params[:types] =
+ [] if search_params[:all_types] == '1' || search_params[:types].nil?
+ search_params[:term_ids] =
+ [] if search_params[:all_terms] == '1' || search_params[:term_ids].nil?
+ search_params[:teacher_ids] =
+ [] if search_params[:all_teachers] == '1' || search_params[:teacher_ids].nil?
+ search_params[:program_ids] =
+ [] if search_params[:all_programs] == '1' || search_params[:program_ids].nil?
search = Sunspot.new_search(Lecture)
# add lectures without term to current term
if Term.active.try(:id).to_i.to_s.in?(search_params[:term_ids])
@@ -663,9 +686,12 @@ def self.search_by(search_params, page)
end
search.build do
with(:sort, search_params[:types]) unless search_params[:types].empty?
- with(:teacher_id, search_params[:teacher_ids]) unless search_params[:teacher_ids].empty?
- with(:program_ids, search_params[:program_ids]) unless search_params[:program_ids].empty?
- with(:term_id, search_params[:term_ids]) unless search_params[:term_ids].empty?
+ with(:teacher_id,
+ search_params[:teacher_ids]) unless search_params[:teacher_ids].empty?
+ with(:program_ids,
+ search_params[:program_ids]) unless search_params[:program_ids].empty?
+ with(:term_id,
+ search_params[:term_ids]) unless search_params[:term_ids].empty?
end
admin = User.find_by_id(search_params[:user_id])&.admin
unless admin
@@ -692,11 +718,13 @@ def self.search_by(search_params, page)
def term_to_label
return term.to_label if term
+
''
end
def term_to_label_short
return term.to_label_short if term
+
''
end
@@ -727,13 +755,13 @@ def previous_assignments
def scheduled_assignments?
media.where(sort: 'Nuesse').where.not(publisher: nil)
- .any? { |m| m.publisher.create_assignment }
+ .any? { |m| m.publisher.create_assignment }
end
def scheduled_assignments
media.where(sort: 'Nuesse').where.not(publisher: nil)
- .select { |m| m.publisher.create_assignment }
- .map { |m| m.publisher.assignment }
+ .select { |m| m.publisher.create_assignment }
+ .map { |m| m.publisher.assignment }
end
def assignments?
@@ -762,111 +790,118 @@ def importable_toc?
def import_toc!(imported_lecture, import_sections, import_tags)
return unless imported_lecture
+
imported_lecture.chapters.each do |c|
new_chapter = c.dup
new_chapter.lecture = self
new_chapter.save
next unless import_sections
+
c.sections.each { |s| s.duplicate_in_chapter(new_chapter, import_tags) }
end
end
private
- # used for after save callback
- def remove_teacher_as_editor
- editors.delete(teacher)
- end
-
- # looks in the cache if there are any media associated *with inheritance*
- # to this lecture and a given project (kaviar, sesam etc.)
- def project_as_user?(project)
- Rails.cache.fetch("#{cache_key_with_version}/#{project}") do
- Medium.where(sort: medium_sort[project],
- released: ['all', 'users', 'subscribers'],
- teachable: self).exists? ||
- Medium.where(sort: medium_sort[project],
- released: ['all', 'users', 'subscribers'],
- teachable: lessons).exists? ||
- Medium.where(sort: medium_sort[project],
- released: ['all', 'users', 'subscribers'],
- teachable: talks).exists? ||
- Medium.where(sort: medium_sort[project],
- released: ['all', 'users', 'subscribers'],
- teachable: course).exists?
- end
- end
-
- def imported_any?(project)
- Rails.cache.fetch("#{cache_key_with_version}/imported_#{project}") do
- imported_media.exists?(sort: medium_sort[project],
- released: ['all', 'users'])
- end
- end
-
- def project?(project, user)
- return project_as_user?(project) unless edited_by?(user) || user.admin
- course_media = if user.in?(course.editors) || user.admin
- Medium.where(sort: medium_sort[project],
- teachable: course).exists?
- else
- Medium.where(sort: medium_sort[project],
- released: ['all', 'users', 'subscribers'],
- teachable: course).exists?
- end
- lecture_media = Medium.where(sort: medium_sort[project],
- teachable: self).exists?
- lesson_media = Medium.where(sort: medium_sort[project],
- teachable: lessons).exists?
- talk_media = Medium.where(sort: medium_sort[project],
+ # used for after save callback
+ def remove_teacher_as_editor
+ editors.delete(teacher)
+ end
+
+ # looks in the cache if there are any media associated *with inheritance*
+ # to this lecture and a given project (kaviar, sesam etc.)
+ def project_as_user?(project)
+ Rails.cache.fetch("#{cache_key_with_version}/#{project}") do
+ Medium.where(sort: medium_sort[project],
+ released: ['all', 'users', 'subscribers'],
+ teachable: self).exists? ||
+ Medium.where(sort: medium_sort[project],
+ released: ['all', 'users', 'subscribers'],
+ teachable: lessons).exists? ||
+ Medium.where(sort: medium_sort[project],
+ released: ['all', 'users', 'subscribers'],
+ teachable: talks).exists? ||
+ Medium.where(sort: medium_sort[project],
+ released: ['all', 'users', 'subscribers'],
+ teachable: course).exists?
+ end
+ end
+
+ def imported_any?(project)
+ Rails.cache.fetch("#{cache_key_with_version}/imported_#{project}") do
+ imported_media.exists?(sort: medium_sort[project],
+ released: ['all', 'users'])
+ end
+ end
+
+ def project?(project, user)
+ return project_as_user?(project) unless edited_by?(user) || user.admin
+
+ course_media = if user.in?(course.editors) || user.admin
+ Medium.where(sort: medium_sort[project],
+ teachable: course).exists?
+ else
+ Medium.where(sort: medium_sort[project],
+ released: ['all', 'users', 'subscribers'],
+ teachable: course).exists?
+ end
+ lecture_media = Medium.where(sort: medium_sort[project],
+ teachable: self).exists?
+ lesson_media = Medium.where(sort: medium_sort[project],
+ teachable: lessons).exists?
+ talk_media = Medium.where(sort: medium_sort[project],
teachable: talks).exists?
- course_media || lecture_media || lesson_media || talk_media
- end
+ course_media || lecture_media || lesson_media || talk_media
+ end
- def medium_sort
- { 'kaviar' => ['Kaviar'], 'sesam' => ['Sesam'], 'kiwi' => ['Kiwi'],
- 'keks' => ['Quiz'], 'nuesse' => ['Nuesse'],
- 'erdbeere' => ['Erdbeere'], 'script' => ['Script'], 'reste' => ['Reste']}
- end
+ def medium_sort
+ { 'kaviar' => ['Kaviar'], 'sesam' => ['Sesam'], 'kiwi' => ['Kiwi'],
+ 'keks' => ['Quiz'], 'nuesse' => ['Nuesse'],
+ 'erdbeere' => ['Erdbeere'], 'script' => ['Script'], 'reste' => ['Reste'] }
+ end
- def touch_media
- media_with_inheritance.update_all(updated_at: Time.now)
- end
+ def touch_media
+ media_with_inheritance.update_all(updated_at: Time.now)
+ end
- def touch_lessons
- lessons.update_all(updated_at: Time.now)
- end
+ def touch_lessons
+ lessons.update_all(updated_at: Time.now)
+ end
- def touch_siblings(lesson)
- lessons.update_all(updated_at: Time.now)
- Medium.where(teachable: lessons).update_all(updated_at: Time.now)
- end
+ def touch_siblings(lesson)
+ lessons.update_all(updated_at: Time.now)
+ Medium.where(teachable: lessons).update_all(updated_at: Time.now)
+ end
- def touch_chapters
- chapters.update_all(updated_at: Time.now)
- end
+ def touch_chapters
+ chapters.update_all(updated_at: Time.now)
+ end
- def touch_sections
- Section.where(chapter: chapters).update_all(updated_at: Time.now)
- end
+ def touch_sections
+ Section.where(chapter: chapters).update_all(updated_at: Time.now)
+ end
- def destroy_forum
- return unless forum
- forum.destroy
- end
+ def destroy_forum
+ return unless forum
- def term_independent?
- return false unless course
- course.term_independent
- end
+ forum.destroy
+ end
- def absence_of_term
- return unless term
- errors.add(:term, :present)
- end
+ def term_independent?
+ return false unless course
- def only_one_lecture
- return unless Lecture.where(course: course).any?
- errors.add(:course, :already_present)
- end
+ course.term_independent
+ end
+
+ def absence_of_term
+ return unless term
+
+ errors.add(:term, :present)
+ end
+
+ def only_one_lecture
+ return unless Lecture.where(course: course).any?
+
+ errors.add(:course, :already_present)
+ end
end
diff --git a/app/models/lesson.rb b/app/models/lesson.rb
index 010568033..852e1dfff 100644
--- a/app/models/lesson.rb
+++ b/app/models/lesson.rb
@@ -11,8 +11,8 @@ class Lesson < ApplicationRecord
# taught in the lesson
has_many :lesson_section_joins, dependent: :destroy
has_many :sections, through: :lesson_section_joins,
- after_remove: :touch_section,
- after_add: :touch_section
+ after_remove: :touch_section,
+ after_add: :touch_section
# being a teachable (course/lecture/lesson), a lesson has associated media
has_many :media, -> { order(position: :asc) },
@@ -40,6 +40,7 @@ class Lesson < ApplicationRecord
def course
return unless lecture.present?
+
lecture.course
end
@@ -100,6 +101,7 @@ def card_header
def card_header_path(user)
return unless user.lectures.include?(lecture)
+
lesson_path
end
@@ -133,11 +135,13 @@ def restricted?
def term
return unless lecture.present?
+
lecture.term
end
def previous
return unless number > 1
+
lecture.lessons[number - 2]
end
@@ -149,7 +153,7 @@ def published_media
media.published
end
- # visible media are published with inheritance and unlocked
+ # visible media are published with inheritance and unlocked
def visible_media_for_user(user)
media.select { |m| m.visible_for_user?(user) }
end
@@ -198,6 +202,7 @@ def visible_items
def content_items
return visible_items if lecture.content_mode == 'video'
+
script_items
end
@@ -207,6 +212,7 @@ def content
def singular_medium
return false if media.count != 1
+
media.first
end
@@ -214,13 +220,16 @@ def singular_medium
# (relevant if lecture content mode is manuscript)
def script_items
return [] unless lecture.manuscript && start_destination && end_destination
+
start_item = Item.where(medium: lecture.manuscript,
pdf_destination: start_destination)&.first
end_item = Item.where(medium: lecture.manuscript,
- pdf_destination: end_destination)&.first
+ pdf_destination: end_destination)&.first
return [] unless start_item && end_item
+
range = (start_item.position..end_item.position).to_a
return [] unless range.present?
+
hidden_chapters = Chapter.where(hidden: true)
hidden_sections = Section.where(hidden: true)
.or(Section.where(chapter: hidden_chapters))
@@ -260,12 +269,14 @@ def self.editable_selection(user)
def guess_start_destination
return start_destination if start_destination
return unless previous
+
probable_start_destination
end
def guess_end_destination
return end_destination if end_destination
return unless previous
+
probable_start_destination
end
@@ -273,11 +284,14 @@ def probable_start_destination
end_item = Item.where(medium: lecture.manuscript,
pdf_destination: previous.end_destination)&.first
return unless end_item
+
position = end_item.position
return unless position
+
successor = lecture.script_items_by_position.where('position > ?', position)
.order(:position)&.first&.pdf_destination
return successor if successor
+
end_item.pdf_destination
end
@@ -287,37 +301,37 @@ def tags_without_section
private
- # path for show lesson action
- def lesson_path
- Rails.application.routes.url_helpers.lesson_path(self)
- end
+ # path for show lesson action
+ def lesson_path
+ Rails.application.routes.url_helpers.lesson_path(self)
+ end
- # used for after save callback
- def touch_media
- lecture.media_with_inheritance.update_all(updated_at: Time.now)
- end
+ # used for after save callback
+ def touch_media
+ lecture.media_with_inheritance.update_all(updated_at: Time.now)
+ end
- def touch_siblings
- lecture.lessons.update_all(updated_at: Time.now)
- end
+ def touch_siblings
+ lecture.lessons.update_all(updated_at: Time.now)
+ end
- def touch_sections
- sections.update_all(updated_at: Time.now)
- chapters = sections.map(&:chapter)
- sections.map(&:chapter).each(&:touch)
- lecture.touch
- end
+ def touch_sections
+ sections.update_all(updated_at: Time.now)
+ chapters = sections.map(&:chapter)
+ sections.map(&:chapter).each(&:touch)
+ lecture.touch
+ end
- def touch_self
- touch
- end
+ def touch_self
+ touch
+ end
- def touch_tags
- tags.update_all(updated_at: Time.now)
- end
+ def touch_tags
+ tags.update_all(updated_at: Time.now)
+ end
- def touch_section(section)
- section.touch
- section.chapter.touch
- end
+ def touch_section(section)
+ section.touch
+ section.chapter.touch
+ end
end
diff --git a/app/models/link.rb b/app/models/link.rb
index 8511878ee..285eef6c0 100644
--- a/app/models/link.rb
+++ b/app/models/link.rb
@@ -17,27 +17,27 @@ class Link < ApplicationRecord
private
- def self_inverse?
- medium_id == linked_medium_id
- end
+ def self_inverse?
+ medium_id == linked_medium_id
+ end
- def create_inverse
- self.class.create(inverse_link_options)
- end
+ def create_inverse
+ self.class.create(inverse_link_options)
+ end
- def destroy_inverses
- inverses.destroy_all
- end
+ def destroy_inverses
+ inverses.destroy_all
+ end
- def inverse?
- self.class.exists?(inverse_link_options) || self_inverse?
- end
+ def inverse?
+ self.class.exists?(inverse_link_options) || self_inverse?
+ end
- def inverses
- self.class.where(inverse_link_options)
- end
+ def inverses
+ self.class.where(inverse_link_options)
+ end
- def inverse_link_options
- { linked_medium_id: medium_id, medium_id: linked_medium_id }
- end
+ def inverse_link_options
+ { linked_medium_id: medium_id, medium_id: linked_medium_id }
+ end
end
diff --git a/app/models/mampf_expression.rb b/app/models/mampf_expression.rb
index 4122ab91b..b0c09afc1 100644
--- a/app/models/mampf_expression.rb
+++ b/app/models/mampf_expression.rb
@@ -16,4 +16,4 @@ def self.trivial_instance
def self.from_hash(content)
MampfExpression.new(content['0'], content['tex'], content['nerd'])
end
-end
\ No newline at end of file
+end
diff --git a/app/models/mampf_matrix.rb b/app/models/mampf_matrix.rb
index 4e2a712a1..fbe5c1562 100644
--- a/app/models/mampf_matrix.rb
+++ b/app/models/mampf_matrix.rb
@@ -18,11 +18,12 @@ def self.trivial_instance
'matrix([0,0],[0,0]')
end
- def entry(i,j)
+ def entry(i, j)
if i > @row_count || j > @column_count
return '0'
end
- @coefficients[(i - 1) * @column_count + (j - 1)]
+
+ @coefficients[(i - 1) * @column_count + (j - 1)]
end
def self.from_hash(content)
diff --git a/app/models/mampf_set.rb b/app/models/mampf_set.rb
index 2b64143b7..333e8d08a 100644
--- a/app/models/mampf_set.rb
+++ b/app/models/mampf_set.rb
@@ -16,4 +16,4 @@ def self.trivial_instance
def self.from_hash(content)
MampfSet.new(content['0'], content['tex'], content['nerd'])
end
-end
\ No newline at end of file
+end
diff --git a/app/models/mampf_tuple.rb b/app/models/mampf_tuple.rb
index df4213fcd..dd997f92a 100644
--- a/app/models/mampf_tuple.rb
+++ b/app/models/mampf_tuple.rb
@@ -16,4 +16,4 @@ def self.trivial_instance
def self.from_hash(content)
MampfTuple.new(content['0'], content['tex'], content['nerd'])
end
-end
\ No newline at end of file
+end
diff --git a/app/models/manuscript.rb b/app/models/manuscript.rb
index 860477733..f11e245e7 100644
--- a/app/models/manuscript.rb
+++ b/app/models/manuscript.rb
@@ -13,6 +13,7 @@ def initialize(medium)
medium.manuscript
return
end
+
@medium = medium
@lecture = medium.teachable.lecture
@locale = @lecture.locale_with_inheritance || I18n.default_locale
@@ -90,6 +91,7 @@ def manuscript_chapter_contradicts?(chapter)
# - creates items and tags for new content, depending on the users choices
def export_to_db!(filter_boxes)
return unless @contradiction_count.zero?
+
create_new_chapters!
@chapters.each do |c|
create_new_sections!(c)
@@ -126,6 +128,7 @@ def create_new_chapters!
# create sections in mampf for those manuscript sections not yet in mampf
def create_new_sections!(chapter)
return if chapter['mampf_chapter'].nil?
+
mampf_chapter = chapter['mampf_chapter']
new_sections_in_chapter(chapter).each do |s|
sect = Section.new(chapter_id: mampf_chapter.id, title: s.second)
@@ -156,7 +159,8 @@ def create_or_update_chapter_items!
description: c['description'],
ref_number: c['label'],
position: nil,
- quarantine: nil })
+ quarantine: nil }
+ )
end
create_or_update_items!(contents, item_details, item_destinations,
item_id_map)
@@ -185,7 +189,8 @@ def create_or_update_section_items!
description: s['description'],
ref_number: s['label'],
position: -1,
- quarantine: nil })
+ quarantine: nil }
+ )
end
create_or_update_items!(contents, item_details, item_destinations,
item_id_map)
@@ -217,7 +222,8 @@ def create_or_update_content_items!(filter_boxes)
ref_number: c['label'],
position: c['counter'],
hidden: filter_boxes[c['counter']].third == false,
- quarantine: nil })
+ quarantine: nil }
+ )
end
create_or_update_items!(contents, item_details, item_destinations,
item_id_map)
@@ -257,11 +263,13 @@ def update_tags!(filter_boxes)
next unless tag
next unless section
next if section.in?(tag.sections)
+
tag.sections |= [section]
tag.courses |= [@lecture.course]
next
end
next unless filter_boxes[c['counter']].second
+
# if checkbox for tag creation is checked, create the tag,
# associate it with course and section
tag = Tag.new(courses: [@lecture.course],
@@ -316,7 +324,7 @@ def add_info_on_item_ids_and_hidden_status
end
end
-# private
+ # private
def get_chapters(bookmarks)
bookmarks.select { |b| b['sort'] == @chapter_marker }
@@ -340,10 +348,10 @@ def match_mampf_chapters
c['mampf_chapter'] = mampf_chapter
c['contradiction'] = if mampf_chapter.nil? ||
mampf_chapter.title == c['description']
- false
- else
- :different_title
- end
+ false
+ else
+ :different_title
+ end
end
end
@@ -359,10 +367,10 @@ def match_mampf_sections
s['mampf_section'] = mampf_section
s['contradiction'] = if mampf_section.nil? ||
mampf_section.title == s['description']
- false
- else
- :different_title
- end
+ false
+ else
+ :different_title
+ end
end
end
@@ -371,12 +379,12 @@ def check_content
bookmarked_chapter_counters = @chapters.map { |c| c['chapter'] }
@content.each do |c|
c['contradiction'] = if !c['chapter'].in?(bookmarked_chapter_counters)
- :missing_chapter
- elsif !c['section'].in?(bookmarked_section_counters)
- :missing_section
- else
- false
- end
+ :missing_chapter
+ elsif !c['section'].in?(bookmarked_section_counters)
+ :missing_section
+ else
+ false
+ end
end
end
@@ -396,6 +404,7 @@ def determine_contradiction_count
def version_info
return [] if @version == DefaultSetting::MAMPF_STY_VERSION
+
[@version.to_s]
end
diff --git a/app/models/medium.rb b/app/models/medium.rb
index 687e24a37..8da3bfc4f 100644
--- a/app/models/medium.rb
+++ b/app/models/medium.rb
@@ -40,12 +40,11 @@ class Medium < ApplicationRecord
has_many :referrals, dependent: :destroy
has_many :referenced_items, through: :referrals, source: :item
-
has_many :imports, dependent: :destroy
has_many :importing_lectures, through: :imports,
- source: :teachable, source_type: 'Lecture'
+ source: :teachable, source_type: 'Lecture'
has_many :importing_courses, through: :imports,
- source: :teachable, source_type: 'Course'
+ source: :teachable, source_type: 'Course'
has_many :quiz_certificates, foreign_key: 'quiz_id', dependent: :destroy
@@ -120,9 +119,13 @@ class Medium < ApplicationRecord
# (they may not be globally visible as their lecture may be unpublished)
scope :published, -> { where.not(released: nil) }
scope :locally_visible, -> { where(released: ['all', 'users']) }
- scope :potentially_visible, -> { where(released: ['all', 'users', 'subscribers']) }
+ scope :potentially_visible, -> {
+ where(released: ['all', 'users', 'subscribers'])
+ }
scope :proper, -> { where.not(sort: 'RandomQuiz') }
- scope :expired, -> { where(sort: 'RandomQuiz').where('created_at < ?', 1.day.ago) }
+ scope :expired, -> {
+ where(sort: 'RandomQuiz').where('created_at < ?', 1.day.ago)
+ }
searchable do
text :description do
@@ -194,7 +197,6 @@ def self.sort_localized_short
'Reste' => I18n.t('categories.reste.short') }
end
-
def self.select_sorts
Medium.sort_localized.except('RandomQuiz').map { |k, v| [v, k] }
end
@@ -230,6 +232,7 @@ def self.select_question
def self.search_all(params)
lecture = Lecture.find_by_id(params[:id])
return Medium.none if lecture.nil?
+
media_in_project = Medium.media_in_project(params[:project])
# media sitting at course level
course_media_in_project = media_in_project.includes(:tags)
@@ -244,6 +247,7 @@ def self.search_all(params)
# returns the ARel of all media for the given project
def self.media_in_project(project)
return Medium.none unless project.present?
+
sort = project == 'keks' ? 'Quiz' : project.capitalize
Medium.where(sort: sort)
end
@@ -263,6 +267,7 @@ def self.search_sorts(search_params)
unless search_params[:all_types] == '0'
return (Medium.sort_enum - ['RandomQuiz'])
end
+
search_params[:types] || []
end
@@ -280,9 +285,10 @@ def self.search_by(search_params, page)
search_params[:types] = [] if search_params[:all_types] == '1'
search_params[:teachable_ids] = TeachableParser.new(search_params)
.teachables_as_strings
- search_params[:editor_ids] = [] if search_params[:all_editors] == '1' || search_params[:all_editors].nil?
+ search_params[:editor_ids] =
+ [] if search_params[:all_editors] == '1' || search_params[:all_editors].nil?
# add media without term to current term
-
+
search_params[:all_terms] = '1' if search_params[:all_terms].blank?
search_params[:all_teachers] = '1' if search_params[:all_teachers].blank?
search_params[:term_ids].push('0') if search_params[:term_ids].present?
@@ -296,8 +302,10 @@ def self.search_by(search_params, page)
without(:sort, Medium.advanced_sorts) unless admin
with(:editor_ids, search_params[:editor_ids])
with(:teachable_compact, search_params[:teachable_ids])
- with(:term_id, search_params[:term_ids]) unless search_params[:all_terms] == '1'
- with(:teacher_id, search_params[:teacher_ids]) unless search_params[:all_teachers] == '1'
+ with(:term_id,
+ search_params[:term_ids]) unless search_params[:all_terms] == '1'
+ with(:teacher_id,
+ search_params[:teacher_ids]) unless search_params[:all_teachers] == '1'
end
if search_params[:purpose] == 'clicker'
search.build do
@@ -315,7 +323,7 @@ def self.search_by(search_params, page)
end
end
unless search_params[:all_tags] == '1' &&
- search_params[:tag_operator] == 'or'
+ search_params[:tag_operator] == 'or'
if search_params[:tag_ids]
if search_params[:tag_operator] == 'or' || search_params[:all_tags] == '1'
search.build do
@@ -375,6 +383,7 @@ def self.similar_courses(search_string)
def restricted?
return false unless teachable
+
teachable.restricted?
end
@@ -386,12 +395,14 @@ def restricted?
# where the user temporarily commented out some part of the manuscript)
def protected_items
return [] unless sort == 'Script'
+
pdf_items = Item.where(medium: self).where.not(pdf_destination: nil)
Referral.where(item: pdf_items).map(&:item).uniq
end
def vanished_items
return [] unless sort == 'Script'
+
Item.where(medium: self)
.where.not(sort: 'self')
.where.not(pdf_destination: manuscript_destinations)
@@ -422,6 +433,7 @@ def quarantine
# return these)
def update_pdf_destinations!
return unless sort == 'Script'
+
irrelevant_items.delete_all
result = missing_items_outside_quarantine.pluck(:pdf_destination)
missing_items_outside_quarantine.update_all(quarantine: true)
@@ -431,6 +443,7 @@ def update_pdf_destinations!
# is the given user an editor of this medium?
def edited_by?(user)
return true if editors.include?(user)
+
false
end
@@ -443,18 +456,20 @@ def edited_with_inheritance_by?(user)
return true if teachable&.lecture&.teacher == user
return true if teachable&.course&.editors&.include?(user)
return true if teachable&.is_a?(Talk) && user.in?(teachable.speakers)
+
false
end
def editors_with_inheritance
return [] if sort == 'RandomQuiz'
+
result = (editors&.to_a + teachable.lecture&.editors.to_a +
[teachable.lecture&.teacher] + teachable.course.editors.to_a).uniq.compact
return result unless teachable.is_a?(Talk)
+
(result + teachable.speakers).uniq
end
-
# creates a .vtt tmp file (and returns it), which contains
# all data needed by the thyme player to realize the toc
def toc_to_vtt
@@ -507,11 +522,13 @@ def referrals_by_time
def screenshot_url_with_host
return screenshot_url(host: host) unless screenshot(:normalized)
+
return screenshot_url(:normalized, host: host)
end
def video_url
return unless video.present?
+
video.url(host: host)
end
@@ -521,36 +538,43 @@ def video_download_url
def video_filename
return unless video.present?
+
video.metadata['filename']
end
def video_size
return unless video.present?
+
video.metadata['size']
end
def video_resolution
return unless video.present?
+
video.metadata['resolution']
end
def video_duration
return unless video.present?
+
video.metadata['duration']
end
def video_duration_hms_string
return unless video.present?
+
TimeStamp.new(total_seconds: video_duration).hms_string
end
def geogebra_filename
return unless geogebra.present?
+
geogebra.metadata['filename']
end
def geogebra_size
return unless geogebra.present?
+
geogebra.metadata['size']
end
@@ -564,11 +588,13 @@ def geogebra_download_url
def geogebra_screenshot_url
return '' unless geogebra.present?
+
geogebra_url(:screenshot, host: host)
end
def manuscript_url_with_host
- return manuscript_url(host: host) + "/"+manuscript_filename if ENV["REWRITE_ENABLED"]=="1"
+ return manuscript_url(host: host) + "/" + manuscript_filename if ENV["REWRITE_ENABLED"] == "1"
+
manuscript_url(host: host)
end
@@ -578,53 +604,62 @@ def manuscript_download_url
def manuscript_filename
return unless manuscript.present?
+
return manuscript.metadata['filename']
end
def manuscript_size
return unless manuscript.present?
+
return manuscript.metadata['size']
end
def manuscript_pages
return unless manuscript.present?
+
return manuscript.metadata['pages']
end
-
def manuscript_screenshot_url
return '' unless manuscript.present?
+
manuscript_url(:screenshot, host: host)
end
def manuscript_destinations
return [] unless manuscript.present? && sort == 'Script'
+
manuscript.metadata['destinations'] || []
end
def video_width
return unless video.present?
+
video_resolution.split('x')[0].to_i
end
def video_height
return unless video.present?
+
video_resolution.split('x')[1].to_i
end
def video_aspect_ratio
return unless video_height != 0 && video_width != 0
+
video_width.to_f / video_height
end
def video_scaled_height(new_width)
return unless video_height != 0 && video_width != 0
+
(new_width.to_f / video_aspect_ratio).to_i
end
def caption
return description if description.present?
return '' unless sort == 'Kaviar' && teachable_type == 'Lesson'
+
teachable.section_titles || ''
end
@@ -644,6 +679,7 @@ def card_subheader
def card_tooltip
return Medium.sort_localized[sort] unless sort == 'Nuesse' && file_last_edited
+
I18n.t('categories.exercises.singular_updated')
end
@@ -653,6 +689,7 @@ def sort_localized
def subheader_style
return 'badge badge-secondary' unless sort == 'Nuesse' && file_last_edited
+
'badge badge-danger'
end
@@ -689,6 +726,7 @@ def visible_for_user?(user)
return true if edited_with_inheritance_by?(user)
return false unless published?
return false if locked?
+
if teachable_type == 'Course'
return false if restricted? && !teachable.in?(user.courses)
end
@@ -700,16 +738,19 @@ def visible_for_user?(user)
def course
return if teachable.nil?
+
teachable.course
end
def lecture
return if teachable.nil?
+
teachable.lecture
end
def lesson
return if teachable.nil?
+
teachable.lesson
end
@@ -720,6 +761,7 @@ def irrelevant?
def teachable_select
return nil unless teachable.present?
+
teachable_type + '-' + teachable_id.to_s
end
@@ -733,6 +775,7 @@ def siblings
def compact_info_uncached
return "#{sort_localized}.#{teachable.compact_title}" unless quizzy?
+
"#{sort_localized}.#{teachable.compact_title}.\##{id}"
end
@@ -749,10 +792,11 @@ def compact_info
def local_info_uncached
return description if description.present?
return I18n.t('admin.medium.local_info.no_title') unless undescribable?
- if sort == 'Kaviar' && teachable_type == 'Lesson'
- return I18n.t('admin.medium.local_info.to_session',
- number: teachable.number,
- date: teachable.date_localized)
+
+ if sort == 'Kaviar' && teachable_type == 'Lesson'
+ return I18n.t('admin.medium.local_info.to_session',
+ number: teachable.number,
+ date: teachable.date_localized)
elsif sort == 'Script'
return I18n.t('categories.script.singular')
@@ -768,6 +812,7 @@ def local_info
def local_info_for_admins_uncached
return local_info unless quizzy?
+
"\##{id}.#{local_info}"
end
@@ -784,6 +829,7 @@ def details_uncached
unless undescribable?
return "#{I18n.t('admin.medium.local_info.no_title')}.ID#{id}"
end
+
''
end
@@ -795,6 +841,7 @@ def details
def title_uncached
return compact_info if details.blank?
+
compact_info + '.' + details
end
@@ -825,14 +872,14 @@ def scoped_teachable_title
# returns info made from sort and description
def local_title_for_viewers_uncached
- return"#{sort_localized}, #{description}" if description.present?
+ return "#{sort_localized}, #{description}" if description.present?
if sort == 'Kaviar' && teachable.class.to_s == 'Lesson'
return "#{I18n.t('categories.kaviar.singular')}, #{teachable.local_title_for_viewers}"
end
+
"#{sort_localized}, #{I18n.t('admin.medium.local_info.no_title')}"
end
-
# returns info made from sort and description
def local_title_for_viewers
Rails.cache.fetch("#{cache_key_with_version}/local_title_for_viewers") do
@@ -868,6 +915,7 @@ def items_with_references
def proper?
return true unless sort == 'RandomQuiz'
+
false
end
@@ -883,14 +931,14 @@ def sanitize_type!
def select_sorts
result = if new_record?
- Medium.sort_localized.except('RandomQuiz')
- elsif sort.in?(['Kaviar', 'Sesam', 'Erdbeere', 'Kiwi', 'Nuesse',
- 'Reste'])
- Medium.sort_localized.except('RandomQuiz', 'Script', 'Quiz',
- 'Question', 'Remark')
- else
- Medium.sort_localized.slice(sort)
- end
+ Medium.sort_localized.except('RandomQuiz')
+ elsif sort.in?(['Kaviar', 'Sesam', 'Erdbeere', 'Kiwi', 'Nuesse',
+ 'Reste'])
+ Medium.sort_localized.except('RandomQuiz', 'Script', 'Quiz',
+ 'Question', 'Remark')
+ else
+ Medium.sort_localized.slice(sort)
+ end
if teachable_type == 'Talk'
result.except!('RandomQuiz', 'Question', 'Remark', 'Erdbeere', 'Script')
end
@@ -924,12 +972,14 @@ def linked_media_ids_cached
def toc_items
return [] unless sort == 'Script'
+
items.where(sort: ['chapter', 'section'])
.natural_sort_by { |x| [x.page, x.ref_number] }
end
def tags_outside_lesson
return Tag.none unless teachable_type == 'Lesson'
+
tags.where.not(id: teachable.tag_ids)
end
@@ -946,16 +996,19 @@ def script_items_importable?
return unless teachable_type == 'Lesson'
return unless teachable.lecture.content_mode == 'manuscript'
return unless teachable.script_items.any?
+
true
end
def import_script_items!
return unless teachable_type == 'Lesson'
return unless teachable.lecture.content_mode == 'manuscript'
+
items = teachable.script_items
return unless items.any?
+
items.each_with_index.each do |i, j|
- Item.create(start_time: TimeStamp.new(h: 0, m:0, s: 0, ms: j),
+ Item.create(start_time: TimeStamp.new(h: 0, m: 0, s: 0, ms: j),
sort: i.sort, description: i.description,
medium: self, section: i.section,
ref_number: i.ref_number,
@@ -972,6 +1025,7 @@ def scoped_teachable
def publish!
return if published?
return unless publisher
+
success = publisher.publish!
update(publisher: nil) if success
end
@@ -979,22 +1033,26 @@ def publish!
def release_date_set?
return false unless publisher
return false unless publisher.release_date
+
true
end
def planned_release_date
return unless publisher
+
publisher.release_date
end
def planned_comment_lock?
return publisher.lock_comments if publisher
+
!!teachable.media_scope.try(:comments_disabled)
end
def becomes_quizzable
return unless type.in?(['Question', 'Remark'])
return becomes(Question) if type == 'Question'
+
becomes(Remark)
end
@@ -1038,8 +1096,8 @@ def supervising_teacher_id
end
def subscribed_users
-
- return teachable.user_ids if ['Lecture', 'Course'].include? teachable.class.to_s
+ return teachable.user_ids if ['Lecture',
+ 'Course'].include? teachable.class.to_s
return unless teachable.class.to_s == 'Lesson'
Lecture.find_by(id: teachable.lecture_id).user_ids
@@ -1047,159 +1105,175 @@ def subscribed_users
private
- # media of type kaviar associated to a lesson and script do not require
- # a description
- def undescribable?
- (sort == 'Kaviar' && teachable.class.to_s == 'Lesson') ||
- sort == 'Script'
- end
+ # media of type kaviar associated to a lesson and script do not require
+ # a description
+ def undescribable?
+ (sort == 'Kaviar' && teachable.class.to_s == 'Lesson') ||
+ sort == 'Script'
+ end
- def quizzy?
- sort.in?(['Quiz', 'Question', 'Remark'])
- end
+ def quizzy?
+ sort.in?(['Quiz', 'Question', 'Remark'])
+ end
- def title_uncached
- return compact_info if details.blank?
- compact_info + '.' + details
- end
+ def title_uncached
+ return compact_info if details.blank?
- def local_title_for_viewers_uncached
- return"#{sort_localized}, #{description}" if description.present?
- if sort == 'Kaviar' && teachable.class.to_s == 'Lesson'
- return "#{I18n.t('categories.kaviar.singular')}, #{teachable.local_title_for_viewers}"
+ compact_info + '.' + details
end
- "#{sort_localized}, #{I18n.t('admin.medium.local_info.no_title')}"
- end
+ def local_title_for_viewers_uncached
+ return "#{sort_localized}, #{description}" if description.present?
+ if sort == 'Kaviar' && teachable.class.to_s == 'Lesson'
+ return "#{I18n.t('categories.kaviar.singular')}, #{teachable.local_title_for_viewers}"
+ end
- def touch_teachable
- return if teachable.nil?
- if teachable.course.present? && teachable.course.persisted?
- teachable.course.touch
+ "#{sort_localized}, #{I18n.t('admin.medium.local_info.no_title')}"
end
- optional_touches
- end
- def reset_released_status
- return if teachable.nil? || teachable.published?
- self.released = nil
- end
+ def touch_teachable
+ return if teachable.nil?
- def optional_touches
- if teachable.lecture.present? && teachable.lecture.persisted?
- teachable.lecture.touch
+ if teachable.course.present? && teachable.course.persisted?
+ teachable.course.touch
+ end
+ optional_touches
end
- if teachable.lesson.present? && teachable.lesson.persisted?
- teachable.lesson.touch
+
+ def reset_released_status
+ return if teachable.nil? || teachable.published?
+
+ self.released = nil
end
- return unless teachable.talk.present? && teachable.talk.persisted?
- teachable.talk.touch
- end
- def vtt_start
- "WEBVTT\n\n"
- end
+ def optional_touches
+ if teachable.lecture.present? && teachable.lecture.persisted?
+ teachable.lecture.touch
+ end
+ if teachable.lesson.present? && teachable.lesson.persisted?
+ teachable.lesson.touch
+ end
+ return unless teachable.talk.present? && teachable.talk.persisted?
- def belongs_to_course?(lecture)
- teachable_type == 'Course' && teachable == lecture.course
- end
+ teachable.talk.touch
+ end
- def belongs_to_lecture?(lecture)
- teachable_type == 'Lecture' && teachable == lecture
- end
+ def vtt_start
+ "WEBVTT\n\n"
+ end
- def belongs_to_lesson?(lecture)
- teachable_type == 'Lesson' && teachable.lecture == lecture
- end
+ def belongs_to_course?(lecture)
+ teachable_type == 'Course' && teachable == lecture.course
+ end
- def create_self_item
- return if sort.in?(['Question', 'Remark', 'RandomQuiz'])
- Item.create(sort: 'self', medium: self)
- end
+ def belongs_to_lecture?(lecture)
+ teachable_type == 'Lecture' && teachable == lecture
+ end
- def local_items
- return teachable.items - items if teachable_type == 'Course'
- teachable.lecture.items - items
- end
+ def belongs_to_lesson?(lecture)
+ teachable_type == 'Lesson' && teachable.lecture == lecture
+ end
+
+ def create_self_item
+ return if sort.in?(['Question', 'Remark', 'RandomQuiz'])
- def at_most_one_manuscript
- return true unless teachable_type == 'Lecture'
- return true unless sort == 'Script'
- if (Medium.where(sort: 'Script',
- teachable: teachable).to_a - [self]).size.positive?
- errors.add(:sort, :lecture_manuscript_exists)
- return false
+ Item.create(sort: 'self', medium: self)
end
- true
- end
- def script_only_for_lectures
- return true if teachable_type == 'Lecture'
- return true unless sort == 'Script'
- errors.add(:sort, :lecture_only)
- false
- end
+ def local_items
+ return teachable.items - items if teachable_type == 'Course'
- def no_video_for_script
- return true unless sort == 'Script'
- return true unless video.present?
- errors.add(:sort, :no_video)
- false
- end
+ teachable.lecture.items - items
+ end
+
+ def at_most_one_manuscript
+ return true unless teachable_type == 'Lecture'
+ return true unless sort == 'Script'
+
+ if (Medium.where(sort: 'Script',
+ teachable: teachable).to_a - [self]).size.positive?
+ errors.add(:sort, :lecture_manuscript_exists)
+ return false
+ end
+ true
+ end
+
+ def script_only_for_lectures
+ return true if teachable_type == 'Lecture'
+ return true unless sort == 'Script'
- def no_changing_sort_to_or_from_script
- if sort_was == 'Script' && sort != 'Script'
- errors.add(:sort, :no_conversion_from_script)
- return false
+ errors.add(:sort, :lecture_only)
+ false
end
- if persisted? && sort_was != 'Script' && sort == 'Script'
- errors.add(:sort, :no_conversion_to_script)
- return false
+
+ def no_video_for_script
+ return true unless sort == 'Script'
+ return true unless video.present?
+
+ errors.add(:sort, :no_video)
+ false
end
- true
- end
- def no_tags_for_scripts
- return true unless sort == 'Script' && tags.any?
- errors.add(:tags, :no_tags_allowed)
- false
- end
+ def no_changing_sort_to_or_from_script
+ if sort_was == 'Script' && sort != 'Script'
+ errors.add(:sort, :no_conversion_from_script)
+ return false
+ end
+ if persisted? && sort_was != 'Script' && sort == 'Script'
+ errors.add(:sort, :no_conversion_to_script)
+ return false
+ end
+ true
+ end
- def delete_vertices
- return unless type.in?(['Question', 'Remark'])
- if type == 'Question'
- becomes(Question).delete_vertices
- return
+ def no_tags_for_scripts
+ return true unless sort == 'Script' && tags.any?
+
+ errors.add(:tags, :no_tags_allowed)
+ false
end
- becomes(Remark).delete_vertices
- end
- def delete_answers
- return unless type == 'Question'
- becomes(Question).answers.delete_all
- end
+ def delete_vertices
+ return unless type.in?(['Question', 'Remark'])
- def text_join
- return unless type.in?(['Question', 'Remark'])
- return text if type == 'Remark'
- "#{text} #{becomes(Question).answers&.map(&:text_join)&.join(' ')}"
- end
+ if type == 'Question'
+ becomes(Question).delete_vertices
+ return
+ end
+ becomes(Remark).delete_vertices
+ end
- def release_state
- return released unless released.nil?
- 'unpublished'
- end
+ def delete_answers
+ return unless type == 'Question'
- def clickerizable?
- return false unless type == 'Question'
- question = becomes(Question)
- return false unless question.answers.count.in?((2..6))
- question.answers.pluck(:value).count(true) == 1
- end
+ becomes(Question).answers.delete_all
+ end
- def answers_count
- return -1 unless type == 'Question'
- becomes(Question).answers.count
- end
-
+ def text_join
+ return unless type.in?(['Question', 'Remark'])
+ return text if type == 'Remark'
+
+ "#{text} #{becomes(Question).answers&.map(&:text_join)&.join(' ')}"
+ end
+
+ def release_state
+ return released unless released.nil?
+
+ 'unpublished'
+ end
+
+ def clickerizable?
+ return false unless type == 'Question'
+
+ question = becomes(Question)
+ return false unless question.answers.count.in?((2..6))
+
+ question.answers.pluck(:value).count(true) == 1
+ end
+
+ def answers_count
+ return -1 unless type == 'Question'
+
+ becomes(Question).answers.count
+ end
end
diff --git a/app/models/medium_publisher.rb b/app/models/medium_publisher.rb
index b1d2ffb5a..1d5923632 100644
--- a/app/models/medium_publisher.rb
+++ b/app/models/medium_publisher.rb
@@ -91,6 +91,7 @@ def publish!
def assignment
return unless @create_assignment
+
Assignment.new(lecture: medium.teachable,
medium_id: @medium_id,
title: @assignment_title,
diff --git a/app/models/notification.rb b/app/models/notification.rb
index e155942c6..278066c89 100644
--- a/app/models/notification.rb
+++ b/app/models/notification.rb
@@ -9,12 +9,12 @@ class Notification < ApplicationRecord
paginates_per 12
-# retrieve notifiable defined by notifiable_type and notifiable_id
-# def notifiable
-# return unless notifiable_type.in?(Notification.allowed_notifiable_types) &&
-# notifiable_id.present?
-# notifiable_type.constantize.find_by_id(notifiable_id)
-# end
+ # retrieve notifiable defined by notifiable_type and notifiable_id
+ # def notifiable
+ # return unless notifiable_type.in?(Notification.allowed_notifiable_types) &&
+ # notifiable_id.present?
+ # notifiable_type.constantize.find_by_id(notifiable_id)
+ # end
# returns the lecture associated to a notification of type announcement,
# and teachable for a notification of type medium, nil otherwise
@@ -22,6 +22,7 @@ def teachable
return unless notifiable.present?
return if notifiable_type.in?(['Lecture', 'Course'])
return notifiable.lecture if notifiable_type == 'Announcement'
+
# notifiable will be a medium, so return its teachable
notifiable.teachable
end
@@ -34,13 +35,16 @@ def teachable
def path(user)
return unless notifiable.present?
return edit_profile_path if notifiable_type.in?(['Course', 'Lecture'])
+
if notifiable_type == 'Announcement'
return notifiable.lecture.path(user) if notifiable.lecture.present?
+
return news_path
end
if notifiable_type == 'Medium' && notifiable.sort == 'Quiz'
return medium_path(notifiable)
end
+
polymorphic_url(notifiable, only_path: true)
end
@@ -52,21 +56,25 @@ def self.allowed_notifiable_types
def medium?
return unless notifiable.present?
+
notifiable_type == 'Medium'
end
def course?
return unless notifiable.present?
+
notifiable.class.to_s == 'Course'
end
def lecture?
return unless notifiable.present?
+
notifiable.class.to_s == 'Lecture'
end
def announcement?
return unless notifiable.present?
+
notifiable.class.to_s == 'Announcement'
end
diff --git a/app/models/notion.rb b/app/models/notion.rb
index 78df58c93..de98a93d9 100644
--- a/app/models/notion.rb
+++ b/app/models/notion.rb
@@ -11,6 +11,7 @@ class Notion < ApplicationRecord
def presence_of_tag
return if tag || aliased_tag
+
errors.add(:tag, :no_tag)
end
@@ -26,9 +27,9 @@ def touch_tag_relations
private
- def clear_tag_cache
- I18n.available_locales.each do |l|
- Rails.cache.delete("tag_select_by_title_#{l}")
+ def clear_tag_cache
+ I18n.available_locales.each do |l|
+ Rails.cache.delete("tag_select_by_title_#{l}")
+ end
end
- end
end
diff --git a/app/models/probe.rb b/app/models/probe.rb
index 6ac6921ec..59b892754 100644
--- a/app/models/probe.rb
+++ b/app/models/probe.rb
@@ -1,5 +1,7 @@
class Probe < InteractionsRecord
- scope :created_between, lambda {|start_date, end_date| where(created_at: start_date.beginning_of_day..end_date.end_of_day)}
+ scope :created_between, lambda { |start_date, end_date|
+ where(created_at: start_date.beginning_of_day..end_date.end_of_day)
+ }
require 'csv'
def self.finished_quizzes(quiz)
@@ -35,10 +37,10 @@ def self.local_success_in_quiz(quiz)
rel_incorrect = total.zero? ? nil : 100 - rel_correct
results[q] = { correct: probes.where(question_id: q,
correct: true).count,
- incorrect: probes.where(question_id: q,
- correct: false).count,
- rel_correct: rel_correct,
- rel_incorrect: rel_incorrect }
+ incorrect: probes.where(question_id: q,
+ correct: false).count,
+ rel_correct: rel_correct,
+ rel_incorrect: rel_incorrect }
end
results
end
@@ -51,9 +53,8 @@ def self.to_csv
csv << attributes
all.each do |probe|
- csv << attributes.map{ |attr| probe.send(attr) }
+ csv << attributes.map { |attr| probe.send(attr) }
end
end
end
-
end
diff --git a/app/models/program.rb b/app/models/program.rb
index 9a2ee1312..1815a27a6 100644
--- a/app/models/program.rb
+++ b/app/models/program.rb
@@ -1,22 +1,22 @@
class Program < ApplicationRecord
- belongs_to :subject
- has_many :divisions, dependent: :destroy
+ belongs_to :subject
+ has_many :divisions, dependent: :destroy
- translates :name
- globalize_accessors locales: I18n.available_locales,
- attributes: translated_attribute_names
+ translates :name
+ globalize_accessors locales: I18n.available_locales,
+ attributes: translated_attribute_names
- def name_with_subject
- "#{subject.name}: #{name}"
- end
+ def name_with_subject
+ "#{subject.name}: #{name}"
+ end
- def courses
- divisions.map(&:courses).flatten
- end
+ def courses
+ divisions.map(&:courses).flatten
+ end
# array of all programs together with their ids for use in options_for_select
def self.select_programs
Program.includes(:subject).all.sort_by(&:name_with_subject)
- .map { |p| [p.name_with_subject, p.id] }
+ .map { |p| [p.name_with_subject, p.id] }
end
end
diff --git a/app/models/question.rb b/app/models/question.rb
index 8dd7c80a9..8d3eb7535 100644
--- a/app/models/question.rb
+++ b/app/models/question.rb
@@ -57,6 +57,7 @@ def self.create_prefilled(label, teachable, editors)
question_sort: 'mc',
solution: solution)
return question if question.invalid?
+
Answer.create(question: question,
text: '0',
value: true)
@@ -98,6 +99,7 @@ def parsed_text_with_params
def text_with_sample_params(parameters)
return text unless parameters.present?
+
result = text
parameters.keys.each do |p|
result.gsub!(/\\para{#{Regexp.escape(p)},(.*?)}/, parameters[p].to_s)
@@ -121,14 +123,14 @@ def self.parameters_from_text(text)
private
- def prelim_answer_table
- table = []
- size = answer_ids.count
- (0..2**size - 1).each do |i|
- hash = {}
- i.to_bool_a(size).each_with_index.map { |x, j| hash[answer_ids[j]] = x }
- table.push(hash)
+ def prelim_answer_table
+ table = []
+ size = answer_ids.count
+ (0..2**size - 1).each do |i|
+ hash = {}
+ i.to_bool_a(size).each_with_index.map { |x, j| hash[answer_ids[j]] = x }
+ table.push(hash)
+ end
+ table
end
- table
- end
end
diff --git a/app/models/quiz.rb b/app/models/quiz.rb
index 5824383f2..bd7871991 100644
--- a/app/models/quiz.rb
+++ b/app/models/quiz.rb
@@ -17,11 +17,13 @@ def label
def publish_vertices!(user, release_state)
return unless vertices
+
vertices.keys.each do |v|
quizzable = quizzable(v)
next if quizzable.published?
next if !quizzable.teachable.published?
next unless user.in?(quizzable.editors_with_inheritance) || user.admin
+
quizzable.update(released: release_state, released_at: Time.now)
end
end
@@ -40,6 +42,7 @@ def quizzables_visible_for_user?(user)
def next_vertex(progress, input = {})
return default_table[progress] if vertices[progress][:type] == 'Remark'
+
target_vertex(progress, input)
end
@@ -50,32 +53,38 @@ def replace_reference!(old_quizzable, new_quizzable, answer_map = {})
def vertices
return if quiz_graph.nil?
+
quiz_graph.vertices
end
def edges
return if quiz_graph.nil?
+
quiz_graph.edges
end
def root
return if quiz_graph.nil?
+
quiz_graph.root
end
def default_table
return if quiz_graph.nil?
+
quiz_graph.default_table
end
def question_ids
return [] unless quiz_graph && quiz_graph.vertices.present?
+
quiz_graph.vertices.select { |_k, v| v[:type] == 'Question' }
.values.map { |v| v[:id] }.uniq
end
def remark_ids
return [] unless quiz_graph && quiz_graph.vertices.present?
+
quiz_graph.vertices.select { |_k, v| v[:type] == 'Remark' }.values
.map { |v| v[:id] }.uniq
end
@@ -98,6 +107,7 @@ def quizzable(vertex_id)
def preselected_branch(vertex_id, crosses, fallback)
successor = next_vertex(vertex_id, crosses)
return successor unless successor == default_table[vertex_id] && fallback
+
0
end
@@ -113,6 +123,7 @@ def questions
def questions_count
return 0 unless quiz_graph
+
quiz_graph.questions_count
end
@@ -124,8 +135,8 @@ def find_errors
private
- def target_vertex(progress, input)
- edges.select { |e, t| e[0] == progress && t.include?(input) }&.keys
- &.first&.second || default_table[progress]
- end
+ def target_vertex(progress, input)
+ edges.select { |e, t| e[0] == progress && t.include?(input) }&.keys
+ &.first&.second || default_table[progress]
+ end
end
diff --git a/app/models/quiz_certificate.rb b/app/models/quiz_certificate.rb
index 2df1ce34e..d08069209 100644
--- a/app/models/quiz_certificate.rb
+++ b/app/models/quiz_certificate.rb
@@ -13,7 +13,7 @@ def self.generate_code
private
- def set_code
- self.code = QuizCertificate.generate_code
- end
+ def set_code
+ self.code = QuizCertificate.generate_code
+ end
end
diff --git a/app/models/quiz_graph.rb b/app/models/quiz_graph.rb
index 6711d0a6b..4688aa013 100644
--- a/app/models/quiz_graph.rb
+++ b/app/models/quiz_graph.rb
@@ -18,6 +18,7 @@ def self.dump(quiz_graph)
def update_vertex(vertex_id, branching, hide)
return if @vertices[vertex_id][:type] == 'Remark'
+
remove_edges_from!(vertex_id)
update_edges_for_question!(vertex_id, branching)
update_hide_solutions!(vertex_id, hide)
@@ -27,6 +28,7 @@ def update_vertex(vertex_id, branching, hide)
def create_vertex(quizzable)
return self if quizzable.blank?
return self if quizzable.invalid?
+
id = new_vertex_id
@vertices[id] = { type: quizzable.class.to_s, id: quizzable.id }
@default_table[id] = 0
@@ -50,8 +52,9 @@ def delete_edge!(source, target)
if @default_table[source] == target
@default_table[source] = 0
end
- answers = @edges[[source,target]]
+ answers = @edges[[source, target]]
return unless answers
+
@edges.delete([source, target])
affected_hide_solution = @hide_solution.select do |h|
h.first == source && h.second.in?(answers)
@@ -68,9 +71,11 @@ def delete_edge!(source, target)
def replace_reference!(old_quizzable, new_quizzable, answer_map = {})
return self unless old_quizzable.class == new_quizzable.class
+
affected_vertices = referencing_vertices(old_quizzable)
affected_vertices.each { |v| @vertices[v][:id] = new_quizzable.id }
return self unless new_quizzable.class.to_s == 'Question'
+
affected_vertices.each do |v|
bend_edges_rereferencing!(edges_from(v), answer_map)
bend_hide_solution_rereferencing!(v, answer_map)
@@ -86,8 +91,11 @@ def reset_vertex_answers_change(id)
def find_errors
return [I18n.t('admin.quiz.no_vertices')] unless @vertices.present?
+
branch_undef = @default_table.values.include?(0)
- no_end = default_table.values.exclude?(-1) && @edges.select { |e| e[1] == -1 }.blank?
+ no_end = default_table.values.exclude?(-1) && @edges.select { |e|
+ e[1] == -1
+ }.blank?
no_root = @root.blank? || @root.zero?
messages = []
messages.push(I18n.t('admin.quiz.undefined_targets')) if branch_undef
@@ -102,6 +110,7 @@ def warnings
def quizzable(id)
return unless id.in?(@vertices.keys)
+
@vertices[id][:type].constantize.find_by_id(@vertices[id][:id])
end
@@ -203,6 +212,7 @@ def referencing_vertices(quizzable)
def new_vertex_id
return 1 unless @vertices.present?
+
@vertices.keys.max + 1
end
@@ -214,6 +224,7 @@ def border_color_for_cytoscape(id)
quizzable = quizzable(id)
return 'orange' unless quizzable.visible?
return 'chocolate' if quizzable.restricted?
+
'#222'
end
@@ -234,7 +245,7 @@ def self.build_from_questions(question_ids)
edges = {}
default_table = {}
size = question_ids.size
- question_ids.each_with_index do |q,i|
+ question_ids.each_with_index do |q, i|
j = i + 1
k = j < size ? j + 1 : -1
question = Question.find_by_id(q)
@@ -253,7 +264,7 @@ def to_cytoscape
background: 'yellowgreen',
borderwidth: '0',
bordercolor: 'grey',
- shape: 'diamond' } )
+ shape: 'diamond' })
# add vertices
@vertices.keys.each do |v|
result.push(data: cytoscape_vertex(v))
@@ -264,13 +275,13 @@ def to_cytoscape
background: 'yellowgreen',
borderwidth: '0',
bordercolor: '#f4a460',
- shape: 'diamond' } )
+ shape: 'diamond' })
# add edges
if @root.in?(@vertices.keys)
result.push(data: { id: "-2-#{@root}",
source: -2,
target: @root,
- color: '#aaa'} )
+ color: '#aaa' })
end
@vertices.keys.each do |v|
edges_from_plus_default(v).each do |e|
@@ -306,11 +317,12 @@ def cytoscape_edge(edge)
end
def questions_count
- @vertices.values.select { |v| v[:type] == 'Question'}.count
+ @vertices.values.select { |v| v[:type] == 'Question' }.count
end
def default?(edge)
return false unless @default_table[edge.first]
+
@default_table[edge.first] == edge.second
end
-end
\ No newline at end of file
+end
diff --git a/app/models/quiz_round.rb b/app/models/quiz_round.rb
index fc9b1322f..17ec833f6 100644
--- a/app/models/quiz_round.rb
+++ b/app/models/quiz_round.rb
@@ -52,6 +52,7 @@ def round_id
def background
return 'bg-grey-lighten-4' if @hide_solution
return 'bg-correct' if @correct
+
'bg-incorrect'
end
@@ -61,75 +62,81 @@ def badge
def statement
return I18n.t('admin.quiz.correct_result') if @correct
+
I18n.t('admin.quiz.incorrect_result')
end
def answers
return [] unless @answer_shuffle
+
@answer_shuffle.map { |a| Answer.find_by_id(a) }
end
def answers_old
return [] unless @answer_shuffle_old
+
@answer_shuffle_old.map { |a| Answer.find_by_id(a) }
end
private
- def progress_counter(params)
- if params[:quiz].present?
- @counter = params[:quiz][:counter].to_i
- @progress = params[:quiz][:progress].to_i
- @session_id = params[:quiz][:session_id]
+ def progress_counter(params)
+ if params[:quiz].present?
+ @counter = params[:quiz][:counter].to_i
+ @progress = params[:quiz][:progress].to_i
+ @session_id = params[:quiz][:session_id]
+ end
+ @progress ||= @quiz.root
+ @counter ||= 0
+ @session_id ||= SecureRandom.uuid.first(13).remove('-')
+ @progress_old = @progress
+ @counter_old = @counter
+ @round_id_old = round_id
end
- @progress ||= @quiz.root
- @counter ||= 0
- @session_id ||= SecureRandom.uuid.first(13).remove('-')
- @progress_old = @progress
- @counter_old = @counter
- @round_id_old = round_id
- end
- def question_details(params)
- @is_question = true
- @question_id = @vertex[:id]
- @answer_scheme = Question.find(@question_id).answer_scheme
- if params[:quiz].present? && params[:quiz][:answer_shuffle].present?
- @answer_shuffle = JSON.parse(params[:quiz][:answer_shuffle]).map(&:to_i)
- else
- @answer_shuffle = Question.find(@question_id).answers.map(&:id).shuffle
+ def question_details(params)
+ @is_question = true
+ @question_id = @vertex[:id]
+ @answer_scheme = Question.find(@question_id).answer_scheme
+ if params[:quiz].present? && params[:quiz][:answer_shuffle].present?
+ @answer_shuffle = JSON.parse(params[:quiz][:answer_shuffle]).map(&:to_i)
+ else
+ @answer_shuffle = Question.find(@question_id).answers.map(&:id).shuffle
+ end
end
- end
- def remark_details(params)
- @is_remark = true
- @remark_id = @vertex[:id]
- end
+ def remark_details(params)
+ @is_remark = true
+ @remark_id = @vertex[:id]
+ end
- def update_answer_shuffle
- @answer_shuffle = Question.find_by_id(@vertex[:id])&.answers&.map(&:id)
- &.shuffle
- end
+ def update_answer_shuffle
+ @answer_shuffle = Question.find_by_id(@vertex[:id])&.answers&.map(&:id)
+ &.shuffle
+ end
- def create_question_probe
- return unless @save_probe
- quiz_id = @quiz.id unless @quiz.sort == 'RandomQuiz'
- input = @solution_input || @input.to_s if @study_participant
- ProbeSaver.perform_async(quiz_id, @question_id, nil, @correct, @progress,
- @session_id, @study_participant, input)
- end
+ def create_question_probe
+ return unless @save_probe
- def create_remark_probe
- return unless @save_probe
- quiz_id = @quiz.id unless @quiz.sort == 'RandomQuiz'
- ProbeSaver.perform_async(quiz_id, nil, @remark_id, nil, @progress,
- @session_id, @study_participant, @input_text)
- end
+ quiz_id = @quiz.id unless @quiz.sort == 'RandomQuiz'
+ input = @solution_input || @input.to_s if @study_participant
+ ProbeSaver.perform_async(quiz_id, @question_id, nil, @correct, @progress,
+ @session_id, @study_participant, input)
+ end
- def create_certificate_final_probe
- return unless @save_probe
- @certificate = QuizCertificate.create(quiz: @quiz)
- ProbeSaver.perform_async(@quiz.id, nil, nil, nil, -1, @session_id,
- @study_participant, nil)
- end
+ def create_remark_probe
+ return unless @save_probe
+
+ quiz_id = @quiz.id unless @quiz.sort == 'RandomQuiz'
+ ProbeSaver.perform_async(quiz_id, nil, @remark_id, nil, @progress,
+ @session_id, @study_participant, @input_text)
+ end
+
+ def create_certificate_final_probe
+ return unless @save_probe
+
+ @certificate = QuizCertificate.create(quiz: @quiz)
+ ProbeSaver.perform_async(@quiz.id, nil, nil, nil, -1, @session_id,
+ @study_participant, nil)
+ end
end
diff --git a/app/models/reader.rb b/app/models/reader.rb
index a49c6c407..0ba906da7 100644
--- a/app/models/reader.rb
+++ b/app/models/reader.rb
@@ -2,6 +2,6 @@
# Reader keeps track of when a user hast last seen a certain thread,
# making it possible to display whether there are new comments
class Reader < ApplicationRecord
- belongs_to :user
- belongs_to :thread, class_name: 'Commontator::Thread'
+ belongs_to :user
+ belongs_to :thread, class_name: 'Commontator::Thread'
end
diff --git a/app/models/referral.rb b/app/models/referral.rb
index 8040a6083..ecf3e6f32 100644
--- a/app/models/referral.rb
+++ b/app/models/referral.rb
@@ -22,6 +22,7 @@ class Referral < ApplicationRecord
# otherwise, return the item's explanation
def explain
return explanation if item.nil?
+
explanation || item.explanation
end
@@ -104,51 +105,56 @@ def item_in_quarantine?
private
- # explanation provided to the vtt file
- # returns the referral's explanation if present, the item's explanation
- # if the item is a link, otherwise nil
- def vtt_explanation
- return explanation if explanation.present?
- return item.explanation if item.sort == 'link' && item.explanation.present?
- end
+ # explanation provided to the vtt file
+ # returns the referral's explanation if present, the item's explanation
+ # if the item is a link, otherwise nil
+ def vtt_explanation
+ return explanation if explanation.present?
+ return item.explanation if item.sort == 'link' && item.explanation.present?
+ end
- # some method that check for valid start and end time
+ # some method that check for valid start and end time
- def valid_start_time
- return true if start_time.nil?
- return true if start_time.valid?
- errors.add(:start_time, :invalid_format)
- false
- end
+ def valid_start_time
+ return true if start_time.nil?
+ return true if start_time.valid?
- def valid_end_time
- return true if end_time.nil?
- return true if end_time.valid?
- errors.add(:end_time, :invalid_format)
- false
- end
+ errors.add(:start_time, :invalid_format)
+ false
+ end
- def start_time_not_too_late
- return true if medium.nil? || !medium.video
- return true unless start_time.valid?
- return true if start_time.total_seconds <= medium.video_duration
- errors.add(:start_time, :too_late)
- false
- end
+ def valid_end_time
+ return true if end_time.nil?
+ return true if end_time.valid?
- def end_time_not_too_late
- return true if medium.nil? || !medium.video
- return true unless end_time.valid?
- return true if end_time.total_seconds <= medium.video_duration
- errors.add(:end_time, :too_late)
- false
- end
+ errors.add(:end_time, :invalid_format)
+ false
+ end
- def end_time_not_too_soon
- return true unless start_time&.valid?
- return true unless end_time&.valid?
- return true if start_time.total_seconds < end_time.total_seconds
- errors.add(:end_time, :too_soon)
- false
- end
+ def start_time_not_too_late
+ return true if medium.nil? || !medium.video
+ return true unless start_time.valid?
+ return true if start_time.total_seconds <= medium.video_duration
+
+ errors.add(:start_time, :too_late)
+ false
+ end
+
+ def end_time_not_too_late
+ return true if medium.nil? || !medium.video
+ return true unless end_time.valid?
+ return true if end_time.total_seconds <= medium.video_duration
+
+ errors.add(:end_time, :too_late)
+ false
+ end
+
+ def end_time_not_too_soon
+ return true unless start_time&.valid?
+ return true unless end_time&.valid?
+ return true if start_time.total_seconds < end_time.total_seconds
+
+ errors.add(:end_time, :too_soon)
+ false
+ end
end
diff --git a/app/models/relation.rb b/app/models/relation.rb
index 533eada78..a3775e48e 100644
--- a/app/models/relation.rb
+++ b/app/models/relation.rb
@@ -13,32 +13,33 @@ class Relation < ApplicationRecord
private
- def create_inverse
- self.class.create(inverse_relation_options)
- end
-
- def destroy_inverses
- inverses.destroy_all
- end
-
- def self_inverse?
- tag_id == related_tag_id
- end
-
- def inverse?
- self.class.exists?(inverse_relation_options) || self_inverse?
- end
-
- def inverses
- self.class.where(inverse_relation_options)
- end
-
- def inverse_relation_options
- { related_tag_id: tag_id, tag_id: related_tag_id }
- end
-
- def touch_tag
- return if tag.nil?
- tag.touch
- end
+ def create_inverse
+ self.class.create(inverse_relation_options)
+ end
+
+ def destroy_inverses
+ inverses.destroy_all
+ end
+
+ def self_inverse?
+ tag_id == related_tag_id
+ end
+
+ def inverse?
+ self.class.exists?(inverse_relation_options) || self_inverse?
+ end
+
+ def inverses
+ self.class.where(inverse_relation_options)
+ end
+
+ def inverse_relation_options
+ { related_tag_id: tag_id, tag_id: related_tag_id }
+ end
+
+ def touch_tag
+ return if tag.nil?
+
+ tag.touch
+ end
end
diff --git a/app/models/section.rb b/app/models/section.rb
index ff4e30f9c..e6287dcfe 100644
--- a/app/models/section.rb
+++ b/app/models/section.rb
@@ -15,7 +15,7 @@ class Section < ApplicationRecord
# a section has many lessons
has_many :lesson_section_joins, dependent: :destroy
has_many :lessons, -> { order(date: :asc, id: :asc) },
- through: :lesson_section_joins
+ through: :lesson_section_joins
# a section needs to have a title
validates :title, presence: true
@@ -42,6 +42,7 @@ def lecture
def reference_number
return calculated_number unless display_number.present?
+
display_number
end
@@ -61,11 +62,13 @@ def reference
def calculated_number
return relative_position unless lecture.absolute_numbering
return absolute_position.to_s unless lecture.start_section.present?
+
(absolute_position + lecture.start_section - 1).to_s
end
def to_label
return displayed_number + '. ' + title unless hidden_with_inheritance?
+
'*' + displayed_number + '. ' + title
end
@@ -75,7 +78,7 @@ def media
lessons.map(&:media).flatten
end
- # visible media are published with inheritance and unlocked
+ # visible media are published with inheritance and unlocked
def visible_media_for_user(user)
media.select { |m| m.visible_for_user?(user) }
end
@@ -85,6 +88,7 @@ def visible_for_user?(user)
return true if lecture.edited_by?(user)
return false unless lecture.published?
return false unless lecture.visible_for_user?(user)
+
true
end
@@ -92,8 +96,10 @@ def previous_preliminary
return higher_item unless first?
return if chapter.first?
return unless previous_chapter
+
potential_last = previous_chapter.sections.last
return potential_last if potential_last.last?
+
potential_last.lower_items.last
end
@@ -112,8 +118,10 @@ def next_preliminary
return lower_item unless last?
return if chapter.last?
return unless next_chapter
+
potential_first = next_chapter.sections.first
return potential_first if potential_first.first?
+
potential_first.higher_items.first
end
@@ -150,6 +158,7 @@ def visible_items_by_time
def visible_items
return visible_items_by_time if lecture.content_mode == 'video'
+
script_items_by_position
end
@@ -166,48 +175,51 @@ def duplicate_in_chapter(new_chapter, import_tags)
new_section.chapter = new_chapter
new_section.save
return unless import_tags
+
new_section.update(tags_order: tags_order)
new_section.tags << tags
end
private
- def touch_lecture
- return unless lecture.present? && lecture.persisted?
- lecture.touch
- end
+ def touch_lecture
+ return unless lecture.present? && lecture.persisted?
- def touch_media
- lecture.media_with_inheritance.update_all(updated_at: Time.current)
- touch
- end
+ lecture.touch
+ end
- def touch_self
- touch
- end
+ def touch_media
+ lecture.media_with_inheritance.update_all(updated_at: Time.current)
+ touch
+ end
- def touch_toc
- return unless lecture.absolute_numbering
- lecture.chapters.update_all(updated_at: Time.now)
- lecture.sections.update_all(updated_at: Time.now)
- end
+ def touch_self
+ touch
+ end
- def relative_position
- chapter.displayed_number + '.' + position.to_s
- end
+ def touch_toc
+ return unless lecture.absolute_numbering
- def absolute_position
- chapter.higher_items.includes(:sections).map(&:sections).flatten.size +
- position
- end
+ lecture.chapters.update_all(updated_at: Time.now)
+ lecture.sections.update_all(updated_at: Time.now)
+ end
- def next_chapter
- # actual next chapter may not have any sections
- chapter.lower_items.find { |c| c.sections.exists? }
- end
+ def relative_position
+ chapter.displayed_number + '.' + position.to_s
+ end
- def previous_chapter
- # actual previous chapter may not have any sections
- chapter.higher_items.find { |c| c.sections.exists? }
- end
+ def absolute_position
+ chapter.higher_items.includes(:sections).map(&:sections).flatten.size +
+ position
+ end
+
+ def next_chapter
+ # actual next chapter may not have any sections
+ chapter.lower_items.find { |c| c.sections.exists? }
+ end
+
+ def previous_chapter
+ # actual previous chapter may not have any sections
+ chapter.higher_items.find { |c| c.sections.exists? }
+ end
end
diff --git a/app/models/section_tag_join.rb b/app/models/section_tag_join.rb
index a8ccf4477..24055766b 100644
--- a/app/models/section_tag_join.rb
+++ b/app/models/section_tag_join.rb
@@ -1,7 +1,7 @@
# SectionTagJoin class
# Join table for section<->tag many-to-many-relation
class SectionTagJoin < ApplicationRecord
- default_scope { order :tag_position }
+ default_scope { order :tag_position }
belongs_to :section
belongs_to :tag
acts_as_list scope: :section, top_of_list: 0, column: :tag_position
diff --git a/app/models/solution.rb b/app/models/solution.rb
index 2d108888c..010ca8f2d 100644
--- a/app/models/solution.rb
+++ b/app/models/solution.rb
@@ -33,19 +33,22 @@ def nerd
def tex
return '' unless @content.tex
+
'$$' + @content.tex + '$$'
end
def tex_mc_answer
return '' unless @content.tex
+
'$' + @content.tex + '$'
end
def self.from_hash(solution_type, content)
return unless solution_type.in?(['MampfExpression', 'MampfMatrix',
'MampfTuple', 'MampfSet'])
+
solution = Solution.new(solution_type.constantize.from_hash(content))
solution.explanation = content[:explanation]
solution
end
-end
\ No newline at end of file
+end
diff --git a/app/models/subject.rb b/app/models/subject.rb
index 063b651a7..110504013 100644
--- a/app/models/subject.rb
+++ b/app/models/subject.rb
@@ -1,9 +1,9 @@
class Subject < ApplicationRecord
- has_many :programs
+ has_many :programs
- translates :name
- globalize_accessors locales: I18n.available_locales,
- attributes: translated_attribute_names
+ translates :name
+ globalize_accessors locales: I18n.available_locales,
+ attributes: translated_attribute_names
def deletable?
programs.none?
diff --git a/app/models/submission.rb b/app/models/submission.rb
index 11d0e5fc8..8b352da41 100644
--- a/app/models/submission.rb
+++ b/app/models/submission.rb
@@ -18,50 +18,56 @@ class Submission < ApplicationRecord
def partners_of_user(user)
return unless user.in?(users)
+
users - [user]
end
def team
- users.map(&:tutorial_name).natural_sort.join(', ')
+ users.map(&:tutorial_name).natural_sort.join(', ')
end
def manuscript_filename
return unless manuscript.present?
+
manuscript.metadata['filename']
end
def manuscript_size
return unless manuscript.present?
+
manuscript.metadata['size']
end
def manuscript_mime_type
- return unless manuscript.present?
+ return unless manuscript.present?
+
manuscript.metadata['mime_type']
end
def correction_filename
return unless correction.present?
+
correction.metadata['filename']
end
def correction_mime_type
- return unless correction.present?
+ return unless correction.present?
+
correction.metadata['mime_type']
end
def correction_size
return unless correction.present?
+
correction.metadata['size']
end
-
def preceding_tutorial(user)
assignment.previous&.map { |a| a.tutorial(user) }&.compact&.first
end
def invited_users
- User.where(id: invited_user_ids)
+ User.where(id: invited_user_ids)
end
def self.generate_token
@@ -72,7 +78,7 @@ def self.generate_token
end
def admissible_invitees(user)
- user.submission_partners(assignment.lecture) - users
+ user.submission_partners(assignment.lecture) - users
end
def in_time?
@@ -85,32 +91,33 @@ def too_late?
def not_updatable?
return false if assignment.active?
+
assignment.totally_expired? || correction.present? || accepted == false
end
- #def file_path(downloadable)
+ # def file_path(downloadable)
# return unless manuscript
# manuscript.to_io.path
# end
- #def correction_file_path
+ # def correction_file_path
# return unless correction
# correction.to_io.path
- #end
-
- def filename_for_bulk_download(end_of_file='')
- (team.first(180) + '-' +
- last_modification_by_users_at.strftime("%F-%H%M") +
- (too_late? ? '-LATE' : '') +
- + '-ID-' + id + end_of_file +
- assignment.accepted_file_type)
- .gsub(/[\x00\/\\:\*\?\"<>\|]/, '_')
- .gsub(/^.*(\\|\/)/, '')
- # Strip out the non-ascii characters
- .gsub(/[^0-9A-Za-z.\-]/, '_')
+ # end
+
+ def filename_for_bulk_download(end_of_file = '')
+ (team.first(180) + '-' +
+ last_modification_by_users_at.strftime("%F-%H%M") +
+ (too_late? ? '-LATE' : '') +
+ + '-ID-' + id + end_of_file +
+ assignment.accepted_file_type)
+ .gsub(/[\x00\/\\:\*\?\"<>\|]/, '_')
+ .gsub(/^.*(\\|\/)/, '')
+ # Strip out the non-ascii characters
+ .gsub(/[^0-9A-Za-z.\-]/, '_')
end
- def self.zip(submissions, downloadables, end_of_file='')
+ def self.zip(submissions, downloadables, end_of_file = '')
begin
archived_filestream = Zip::OutputStream.write_buffer do |stream|
submissions.zip(downloadables).each do |s, d|
@@ -128,85 +135,91 @@ def self.zip(submissions, downloadables, end_of_file='')
def self.zip_submissions!(tutorial, assignment)
submissions = Submission.where(tutorial: tutorial,
assignment: assignment).proper
- manuscripts = submissions.collect { |s| s.manuscript if s.manuscript.present? }
+ manuscripts = submissions.collect { |s|
+ s.manuscript if s.manuscript.present?
+ }
zip(submissions, manuscripts)
end
def self.zip_corrections!(tutorial, assignment)
submissions = Submission.where(tutorial: tutorial,
assignment: assignment).proper
- corrections = submissions.collect { |s| s.correction if s.correction.present? }
+ corrections = submissions.collect { |s|
+ s.correction if s.correction.present?
+ }
zip(submissions, corrections, '-correction')
end
-
###
# Checks size and if filetype is acceptable
###
def check_file_properties_any(metadata, sort)
errors = []
- if sort == :submission && metadata['size'] > 10*1024*1024
+ if sort == :submission && metadata['size'] > 10 * 1024 * 1024
errors.push I18n.t('submission.manuscript_size_too_big',
max_size: '10 MB')
end
- if sort == :correction && metadata['size'] > 15*1024*1024
+ if sort == :correction && metadata['size'] > 15 * 1024 * 1024
errors.push I18n.t('submission.manuscript_size_too_big',
max_size: '15 MB')
end
file_name = metadata['filename']
file_type = File.extname(file_name)
- if !file_type.in?(['.cc', '.hh', '.m',".mlx", '.pdf', '.zip',".txt"])
+ if !file_type.in?(['.cc', '.hh', '.m', ".mlx", '.pdf', '.zip', ".txt"])
errors.push I18n.t('submission.wrong_file_type',
file_type: file_type,
accepted_file_type: assignment.accepted_file_type)
end
return {} unless errors.present?
+
{ sort => errors }
end
+
def check_file_properties(metadata, sort)
errors = []
- if sort == :submission && metadata['size'] > 10*1024*1024
+ if sort == :submission && metadata['size'] > 10 * 1024 * 1024
errors.push I18n.t('submission.manuscript_size_too_big',
max_size: '10 MB')
end
- if sort == :correction && metadata['size'] > 15*1024*1024
+ if sort == :correction && metadata['size'] > 15 * 1024 * 1024
errors.push I18n.t('submission.manuscript_size_too_big',
max_size: '15 MB')
end
file_name = metadata['filename']
file_type = File.extname(file_name)
if file_type != assignment.accepted_file_type &&
- assignment.accepted_file_type != '.tar.gz'
+ assignment.accepted_file_type != '.tar.gz'
errors.push I18n.t('submission.wrong_file_type',
file_type: file_type,
accepted_file_type: assignment.accepted_file_type)
end
if assignment.accepted_file_type == '.tar.gz'
- if file_type == '.gz'
- reduced_type = File.extname(File.basename(file_name, '.gz'))
- if reduced_type != '.tar'
- errors.push I18n.t('submission.wrong_file_type',
- file_type: '.gz',
- accepted_file_type: '.tar.gz')
+ if file_type == '.gz'
+ reduced_type = File.extname(File.basename(file_name, '.gz'))
+ if reduced_type != '.tar'
+ errors.push I18n.t('submission.wrong_file_type',
+ file_type: '.gz',
+ accepted_file_type: '.tar.gz')
end
else
- errors.push I18n.t('submission.wrong_file_type',
- file_type: file_type,
- accepted_file_type: '.tar.gz')
- end
+ errors.push I18n.t('submission.wrong_file_type',
+ file_type: file_type,
+ accepted_file_type: '.tar.gz')
+ end
end
if (!assignment.accepted_file_type.in?(['.cc', '.hh', '.m']) &&
!metadata['mime_type'].in?(assignment.accepted_mime_types)) ||
- (assignment.accepted_file_type.in?(['.cc', '.hh', '.m']) &&
- (!metadata['mime_type'].starts_with?('text/') &&
- metadata['mime_type'] != 'application/octet-stream'))
+ (assignment.accepted_file_type.in?(['.cc', '.hh', '.m']) &&
+ (!metadata['mime_type'].starts_with?('text/') &&
+ metadata['mime_type'] != 'application/octet-stream'))
errors.push I18n.t('submission.wrong_mime_type',
- mime_type: metadata['mime_type'],
- accepted_mime_types: assignment.accepted_mime_types
- .join(', '))
+ mime_type: metadata['mime_type'],
+ accepted_mime_types: assignment.accepted_mime_types
+ .join(', '))
end
return {} unless errors.present?
+
{ sort => errors }
end
@@ -214,7 +227,7 @@ def self.bulk_corrections!(tutorial, assignment, files)
submissions = Submission.where(tutorial: tutorial,
assignment: assignment).proper
report = { successful_saves: [], submissions: submissions.size,
- invalid_filenames: [], invalid_id: [], in_subfolder: [],
+ invalid_filenames: [], invalid_id: [], in_subfolder: [],
no_decision: [], rejected: [], invalid_file: [] }
tmp_folder = Dir.mktmpdir
begin
@@ -225,7 +238,7 @@ def self.bulk_corrections!(tutorial, assignment, files)
next
end
submission_id = File.basename(filename.split('-ID-').last,
- File.extname(filename.split('-ID-').last))
+ File.extname(filename.split('-ID-').last))
submission = Submission.find_by_id(submission_id)
if !submission
report[:invalid_id].push(filename)
@@ -254,44 +267,45 @@ def self.bulk_corrections!(tutorial, assignment, files)
private
- def matching_lecture
- return true if tutorial&.lecture == assignment&.lecture
- errors.add(:tutorial, :lecture_not_matching)
- end
+ def matching_lecture
+ return true if tutorial&.lecture == assignment&.lecture
- def set_token
- self.token = Submission.generate_token
- end
+ errors.add(:tutorial, :lecture_not_matching)
+ end
- def self.number_of_submissions(tutorial, assignment)
- Submission.where(tutorial: tutorial, assignment: assignment)
- .where.not(manuscript_data: nil).size
- end
+ def set_token
+ self.token = Submission.generate_token
+ end
- def self.number_of_corrections(tutorial, assignment)
- Submission.where(tutorial: tutorial, assignment: assignment)
- .where.not(correction_data: nil).size
- end
+ def self.number_of_submissions(tutorial, assignment)
+ Submission.where(tutorial: tutorial, assignment: assignment)
+ .where.not(manuscript_data: nil).size
+ end
- def self.number_of_late_submissions(tutorial, assignment)
- Submission.where(tutorial: tutorial, assignment: assignment)
- .where.not(manuscript_data: nil)
- .select { |s| s.too_late? }.size
- end
+ def self.number_of_corrections(tutorial, assignment)
+ Submission.where(tutorial: tutorial, assignment: assignment)
+ .where.not(correction_data: nil).size
+ end
- def self.submissions_total(assignment)
- Submission.where(assignment: assignment)
- .where.not(manuscript_data: nil).size
- end
+ def self.number_of_late_submissions(tutorial, assignment)
+ Submission.where(tutorial: tutorial, assignment: assignment)
+ .where.not(manuscript_data: nil)
+ .select { |s| s.too_late? }.size
+ end
- def self.corrections_total(assignment)
- Submission.where(assignment: assignment)
- .where.not(correction_data: nil).size
- end
+ def self.submissions_total(assignment)
+ Submission.where(assignment: assignment)
+ .where.not(manuscript_data: nil).size
+ end
- def self.late_submissions_total(assignment)
- Submission.where(assignment: assignment)
- .where.not(manuscript_data: nil)
- .select { |s| s.too_late? }.size
- end
+ def self.corrections_total(assignment)
+ Submission.where(assignment: assignment)
+ .where.not(correction_data: nil).size
+ end
+
+ def self.late_submissions_total(assignment)
+ Submission.where(assignment: assignment)
+ .where.not(manuscript_data: nil)
+ .select { |s| s.too_late? }.size
+ end
end
diff --git a/app/models/submission_cleaner.rb b/app/models/submission_cleaner.rb
index 9f4e7681f..5a91644cc 100644
--- a/app/models/submission_cleaner.rb
+++ b/app/models/submission_cleaner.rb
@@ -50,75 +50,75 @@ def check_for_deletion
private
- def clear_props
- @assignments = nil
- @submitters = nil
- @lectures = nil
- end
+ def clear_props
+ @assignments = nil
+ @submitters = nil
+ @lectures = nil
+ end
- def fetch_props
- clear_props
- @assignments = Assignment.where(deletion_date: @deletion_date)
- return if @assignments.empty?
+ def fetch_props
+ clear_props
+ @assignments = Assignment.where(deletion_date: @deletion_date)
+ return if @assignments.empty?
- @submitters = User.where(id: @assignments.flat_map(&:submitter_ids))
- @lectures = Lecture.where(id: @assignments.pluck(:lecture_id))
- end
+ @submitters = User.where(id: @assignments.flat_map(&:submitter_ids))
+ @lectures = Lecture.where(id: @assignments.pluck(:lecture_id))
+ end
- def send_destruction_mail_to_submitters
- return if @submitters.blank?
+ def send_destruction_mail_to_submitters
+ return if @submitters.blank?
- I18n.available_locales.each do |l|
- local_submitter_ids = @submitters.where(locale: l).pluck(:id)
- next if local_submitter_ids.empty?
+ I18n.available_locales.each do |l|
+ local_submitter_ids = @submitters.where(locale: l).pluck(:id)
+ next if local_submitter_ids.empty?
- local_submitter_ids.in_groups_of(200, false) do |group|
- NotificationMailer.with(recipients: group,
- deletion_date: @deletion_date,
- locale: l)
- .submission_destruction_email.deliver_now
+ local_submitter_ids.in_groups_of(200, false) do |group|
+ NotificationMailer.with(recipients: group,
+ deletion_date: @deletion_date,
+ locale: l)
+ .submission_destruction_email.deliver_now
+ end
end
end
- end
- def send_destruction_mail_to_editors
- @lectures.each do |l|
- editor_ids = l.editors.pluck(:id) + [l.teacher.id]
- NotificationMailer.with(recipients: editor_ids,
- lecture: l,
- deletion_date: @deletion_date,
- locale: l.locale)
- .submission_destruction_lecture_email.deliver_now
+ def send_destruction_mail_to_editors
+ @lectures.each do |l|
+ editor_ids = l.editors.pluck(:id) + [l.teacher.id]
+ NotificationMailer.with(recipients: editor_ids,
+ lecture: l,
+ deletion_date: @deletion_date,
+ locale: l.locale)
+ .submission_destruction_lecture_email.deliver_now
+ end
end
- end
-
- def send_info_mail_to_submitters
- return if @submitters.blank?
- I18n.available_locales.each do |l|
- local_submitter_ids = @submitters.where(locale: l).pluck(:id)
- next if local_submitter_ids.empty?
+ def send_info_mail_to_submitters
+ return if @submitters.blank?
+
+ I18n.available_locales.each do |l|
+ local_submitter_ids = @submitters.where(locale: l).pluck(:id)
+ next if local_submitter_ids.empty?
+
+ local_submitter_ids.in_groups_of(200, false) do |group|
+ NotificationMailer.with(recipients: group,
+ deletion_date: @deletion_date,
+ reminder: @reminder,
+ lectures: @lectures,
+ locale: l)
+ .submission_deletion_email.deliver_now
+ end
+ end
+ end
- local_submitter_ids.in_groups_of(200, false) do |group|
- NotificationMailer.with(recipients: group,
+ def send_info_mail_to_editors
+ @lectures.each do |l|
+ editor_ids = l.editors.pluck(:id) + [l.teacher.id]
+ NotificationMailer.with(recipients: editor_ids,
+ lecture: l,
deletion_date: @deletion_date,
reminder: @reminder,
- lectures: @lectures,
- locale: l)
- .submission_deletion_email.deliver_now
+ locale: l.locale)
+ .submission_deletion_lecture_email.deliver_now
end
end
- end
-
- def send_info_mail_to_editors
- @lectures.each do |l|
- editor_ids = l.editors.pluck(:id) + [l.teacher.id]
- NotificationMailer.with(recipients: editor_ids,
- lecture: l,
- deletion_date: @deletion_date,
- reminder: @reminder,
- locale: l.locale)
- .submission_deletion_lecture_email.deliver_now
- end
- end
end
diff --git a/app/models/tag.rb b/app/models/tag.rb
index dc37e6361..42d1499a0 100644
--- a/app/models/tag.rb
+++ b/app/models/tag.rb
@@ -38,15 +38,19 @@ class Tag < ApplicationRecord
serialize :realizations, Array
accepts_nested_attributes_for :notions,
- reject_if: lambda {|attributes| attributes['title'].blank?},
- allow_destroy: true
+ reject_if: lambda { |attributes|
+ attributes['title'].blank?
+ },
+ allow_destroy: true
validates_presence_of :notions
validates_associated :notions
accepts_nested_attributes_for :aliases,
- reject_if: lambda {|attributes| attributes['title'].blank?},
- allow_destroy: true
+ reject_if: lambda { |attributes|
+ attributes['title'].blank?
+ },
+ allow_destroy: true
validates_associated :aliases
@@ -84,6 +88,7 @@ def extended_title_uncached
unless other_titles_uncached.any?
return local_title_uncached + " (#{aliases.pluck(:title).join(', ')})"
end
+
local_title_uncached +
" (#{aliases.pluck(:title).join(', ')}," +
" #{other_titles_uncached.join(', ')})"
@@ -144,7 +149,6 @@ def self.select_with_substring(search_string)
.map { |t| { value: t.id, text: t.title } }
end
-
# returns all tags whose title is close to the given search string
# wrt to the JaroWinkler metric
def self.similar_tags(search_string)
@@ -174,7 +178,7 @@ def self.select_by_title
def self.select_by_title_except(excluded_tags)
Tag.where.not(id: excluded_tags.pluck(:id))
.map { |t| t.extended_title_id_hash }
- .natural_sort_by{ |t| t[:title] }.map { |t| [t[:title], t[:id]] }
+ .natural_sort_by { |t| t[:title] }.map { |t| [t[:title], t[:id]] }
end
# converts the subgraph of all tags of distance <= 2 to the given marked tag
@@ -208,6 +212,7 @@ def realizations_cached
# search params is a hash having keys :all_tags, :tag_ids
def self.search_tags(search_params)
return Tag.all unless search_params[:all_tags] == '0'
+
tag_ids = search_params[:tag_ids] || []
Tag.where(id: tag_ids)
end
@@ -238,6 +243,7 @@ def tags_in_neighbourhood
def short_title(max_letters = 30)
return title unless title.length > max_letters
+
title[0, max_letters - 3] + '...'
end
@@ -265,6 +271,7 @@ def lectures
def create_random_quiz!(user)
questions = visible_questions(user)
return unless questions.any?
+
question_ids = questions.pluck(:id).sample(5)
quiz_graph = QuizGraph.build_from_questions(question_ids)
quiz = Quiz.new(description: "#{I18n.t('categories.randomquiz.singular')} #{title} #{Time.now}",
@@ -273,6 +280,7 @@ def create_random_quiz!(user)
sort: 'RandomQuiz')
quiz.save
return quiz.errors unless quiz.valid?
+
quiz
end
@@ -281,6 +289,7 @@ def create_random_quiz!(user)
def color(marked_tag, highlight_related_tags: true)
return '#f00' if self == marked_tag
return '#ff8c00' if highlight_related_tags && in?(marked_tag.related_tags)
+
'#000'
end
@@ -289,6 +298,7 @@ def color(marked_tag, highlight_related_tags: true)
def background(marked_tag, highlight_related_tags: true)
return '#f00' if self == marked_tag
return '#ff8c00' if highlight_related_tags && in?(marked_tag.related_tags)
+
'#666'
end
@@ -313,7 +323,9 @@ def cytoscape_edge(related_tag)
# published sections are sections that belong to a published lecture
def visible_sections(user)
- user.filter_sections(sections).select { |s| s.lecture.visible_for_user?(user) }
+ user.filter_sections(sections).select { |s|
+ s.lecture.visible_for_user?(user)
+ }
end
def cache_key
@@ -343,6 +355,7 @@ def identify_with!(tag)
related_tags.delete(tag)
tag.sections.each do |s|
next unless self.in?(s.tags)
+
old_section_tag = SectionTagJoin.find_by(section: s, tag: tag)
position = old_section_tag.tag_position
new_section_tag = SectionTagJoin.find_by(section: s, tag: self)
@@ -369,24 +382,25 @@ def visible_questions(user)
private
- def touch_relations(notion)
- if persisted?
- touch
- touch_lectures
- touch_sections
- touch_chapters
+ def touch_relations(notion)
+ if persisted?
+ touch
+ touch_lectures
+ touch_sections
+ touch_chapters
+ end
end
- end
- # simulates the after_destroy callback for relations
- def destroy_relations(related_tag)
- Relation.where(tag: [self, related_tag],
- related_tag: [self, related_tag]).delete_all
- end
+ # simulates the after_destroy callback for relations
+ def destroy_relations(related_tag)
+ Relation.where(tag: [self, related_tag],
+ related_tag: [self, related_tag]).delete_all
+ end
- def title_join
- result = notions.pluck(:title).join(' ')
- return result unless aliases.any?
- result + ' ' + aliases.pluck(:title).join(' ')
- end
+ def title_join
+ result = notions.pluck(:title).join(' ')
+ return result unless aliases.any?
+
+ result + ' ' + aliases.pluck(:title).join(' ')
+ end
end
diff --git a/app/models/talk.rb b/app/models/talk.rb
index e34fbf05e..5b528e139 100644
--- a/app/models/talk.rb
+++ b/app/models/talk.rb
@@ -8,7 +8,7 @@ class Talk < ApplicationRecord
# being a teachable (course/lecture/lesson), a talk has associated media
has_many :media, -> { order(position: :asc) }, as: :teachable,
- dependent: :destroy
+ dependent: :destroy
# a talk has many tags
has_many :talk_tag_joins, dependent: :destroy
diff --git a/app/models/term.rb b/app/models/term.rb
index 43279cd49..36009cad4 100644
--- a/app/models/term.rb
+++ b/app/models/term.rb
@@ -41,6 +41,7 @@ def end_date
# label contains season and year(s) with all digits
def to_label
return unless season.present?
+
season + ' ' + year_corrected
end
@@ -101,12 +102,15 @@ def self.possible_deletion_dates
end
def self.possible_deletion_dates_localized
- possible_deletion_dates.map { |d| d.strftime(I18n.t('date.formats.concise')) }
+ possible_deletion_dates.map { |d|
+ d.strftime(I18n.t('date.formats.concise'))
+ }
end
# array of all terms together with their ids for use in options_for_select
def self.select_terms(independent = false)
return ['bla', nil] if independent
+
Term.all.sort_by(&:begin_date).reverse.map { |t| [t.to_label, t.id] }
end
@@ -120,24 +124,26 @@ def self.previous_by_date(date)
private
- def year_corrected
- return year.to_s unless season == 'WS'
- year.to_s + '/' + ((year % 100) + 1).to_s
- end
+ def year_corrected
+ return year.to_s unless season == 'WS'
- def year_corrected_short
- return (year % 100).to_s unless season == 'WS'
- (year % 100).to_s + '/' + ((year % 100) + 1).to_s
- end
+ year.to_s + '/' + ((year % 100) + 1).to_s
+ end
- def touch_lectures_and_lessons
- lectures.update_all(updated_at: Time.now)
- Lesson.where(lecture: lectures).update_all(updated_at: Time.now)
- end
+ def year_corrected_short
+ return (year % 100).to_s unless season == 'WS'
- def touch_media
- Medium.where(teachable: lectures).update_all(updated_at: Time.now)
- Medium.where(teachable: Lesson.where(lecture: lectures))
- .update_all(updated_at: Time.now)
- end
+ (year % 100).to_s + '/' + ((year % 100) + 1).to_s
+ end
+
+ def touch_lectures_and_lessons
+ lectures.update_all(updated_at: Time.now)
+ Lesson.where(lecture: lectures).update_all(updated_at: Time.now)
+ end
+
+ def touch_media
+ Medium.where(teachable: lectures).update_all(updated_at: Time.now)
+ Medium.where(teachable: Lesson.where(lecture: lectures))
+ .update_all(updated_at: Time.now)
+ end
end
diff --git a/app/models/time_stamp.rb b/app/models/time_stamp.rb
index d5232735c..1924e36bb 100644
--- a/app/models/time_stamp.rb
+++ b/app/models/time_stamp.rb
@@ -81,27 +81,28 @@ def total_seconds
private
- def init_with_total_seconds(total_s)
- floor_s = total_s.floor
- @milliseconds = ((total_s - floor_s) * 1000).round
- @minutes = (floor_s / 60) % 60
- @seconds = floor_s % 60
- @hours = floor_s / (60 * 60)
- end
+ def init_with_total_seconds(total_s)
+ floor_s = total_s.floor
+ @milliseconds = ((total_s - floor_s) * 1000).round
+ @minutes = (floor_s / 60) % 60
+ @seconds = floor_s % 60
+ @hours = floor_s / (60 * 60)
+ end
- def init_with_time_string(time_string)
- return unless /(\d+):([0-5]\d):([0-5]\d).(\d{3})/.match?(time_string)
- matchdata = /(\d):([0-5]\d):([0-5]\d).(\d{3})/.match(time_string)
- @hours = matchdata[1].to_i
- @minutes = matchdata[2].to_i
- @seconds = matchdata[3].to_i
- @milliseconds = matchdata[4].to_i
- end
+ def init_with_time_string(time_string)
+ return unless /(\d+):([0-5]\d):([0-5]\d).(\d{3})/.match?(time_string)
- def init_with_hms(params)
- @hours = params[:h].to_i
- @minutes = params[:m].to_i
- @seconds = params[:s].to_i
- @milliseconds = params[:ms].to_i
- end
+ matchdata = /(\d):([0-5]\d):([0-5]\d).(\d{3})/.match(time_string)
+ @hours = matchdata[1].to_i
+ @minutes = matchdata[2].to_i
+ @seconds = matchdata[3].to_i
+ @milliseconds = matchdata[4].to_i
+ end
+
+ def init_with_hms(params)
+ @hours = params[:h].to_i
+ @minutes = params[:m].to_i
+ @seconds = params[:s].to_i
+ @milliseconds = params[:ms].to_i
+ end
end
diff --git a/app/models/tutorial.rb b/app/models/tutorial.rb
index b093de301..60611c8a7 100644
--- a/app/models/tutorial.rb
+++ b/app/models/tutorial.rb
@@ -14,20 +14,21 @@ class Tutorial < ApplicationRecord
validates :title, uniqueness: { scope: [:lecture_id] }, presence: true
def title_with_tutors
- return "#{title}, #{I18n.t('basics.tba')}" unless tutors.any?
- "#{title}, #{tutor_names}"
+ return "#{title}, #{I18n.t('basics.tba')}" unless tutors.any?
+
+ "#{title}, #{tutor_names}"
end
def tutor_names
- return unless tutors.any?
- tutors.map(&:tutorial_name).join(', ')
+ return unless tutors.any?
+
+ tutors.map(&:tutorial_name).join(', ')
end
def destructible?
- Submission.where(tutorial: self).proper.none?
+ Submission.where(tutorial: self).proper.none?
end
-
def teams_to_csv(assignment)
submissions = Submission.where(tutorial: self, assignment: assignment)
.proper.order(:last_modification_by_users_at)
@@ -37,11 +38,11 @@ def teams_to_csv(assignment)
end
end
end
-
+
private
- def check_destructibility
- throw(:abort) unless destructible?
- true
- end
+ def check_destructibility
+ throw(:abort) unless destructible?
+ true
+ end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 58a29840f..0c4dec0a8 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -66,7 +66,8 @@ class User < ApplicationRecord
# if a homepage is given it should at leat be a valid address
validates :homepage, http_url: true, if: :homepage?
- validates :locale, inclusion: { in: I18n.available_locales.map(&:to_s) }, if: :locale?
+ validates :locale, inclusion: { in: I18n.available_locales.map(&:to_s) },
+ if: :locale?
# a user needs to give a display name
validates :name, presence: true, if: :persisted?
@@ -101,7 +102,6 @@ class User < ApplicationRecord
text :tutorial_name
end
-
# returns the array of all teachers
def self.teachers
User.where(id: Lecture.pluck(:teacher_id).uniq)
@@ -137,6 +137,7 @@ def self.only_editors_selection
# search params is a hash having keys :all_editors, :editor_ids
def self.search_editors(search_params)
return User.editors unless search_params[:all_editors] == '0'
+
editor_ids = search_params[:editor_ids] || []
User.where(id: editor_ids)
end
@@ -145,7 +146,7 @@ def self.search_editors(search_params)
# (e.g. in a select editors form)
def self.select_editors
User.pluck(:name, :email, :id, :name_in_tutorials)
- .map { |u| [ "#{u.fourth.presence || u.first} (#{u.second})", u.third] }
+ .map { |u| ["#{u.fourth.presence || u.first} (#{u.second})", u.third] }
end
def self.name_or_email_like(search_string)
@@ -165,14 +166,17 @@ def self.preferred_name_or_email_like(search_string)
return User.none unless search_string.length >= 2
where(name_in_tutorials: [nil, '']).name_or_email_like(search_string)
- .or(where.not(name_in_tutorials: [nil, ''])
+ .or(where.not(name_in_tutorials: [nil,
+ ''])
.name_in_tutorials_or_email_like(search_string))
end
def self.values_for_select
pluck(:id, :name, :name_in_tutorials, :email)
- .map { |u| { value: u.first,
- text: "#{ u.third.presence || u.second } (#{u.fourth})" } }
+ .map { |u|
+ { value: u.first,
+ text: "#{u.third.presence || u.second} (#{u.fourth})" }
+ }
end
def courses
@@ -186,11 +190,13 @@ def courses
# - all courses that the user has subscribed to (if subscription type is 3)
def related_courses(overrule_subscription_type: false)
return if subscription_type.nil?
+
selection_type = overrule_subscription_type || subscription_type
if selection_type == 1
return Course.where(id: preceding_course_ids).includes(:lectures)
end
return Course.all.includes(:lectures) if selection_type == 2
+
courses
end
@@ -214,8 +220,10 @@ def related_lectures
# returns ARel of all those tags from the given tags that belong to
# the user's related lectures
def filter_tags(tags)
- Tag.where(id: tags.select { |t| t.in_lectures?(related_lectures) ||
- t.in_courses?(related_courses) }
+ Tag.where(id: tags.select { |t|
+ t.in_lectures?(related_lectures) ||
+ t.in_courses?(related_courses)
+ }
.map(&:id))
end
@@ -229,9 +237,9 @@ def filter_lectures(lectures)
# the user's related lectures
def filter_media(media)
media.where(teachable: related_lectures)
- .or(media.where(teachable: related_courses))
- .or(media.where(teachable: Lesson.where(lecture: related_lectures)))
- .or(media.where(teachable: Talk.where(lecture: related_lectures)))
+ .or(media.where(teachable: related_courses))
+ .or(media.where(teachable: Lesson.where(lecture: related_lectures)))
+ .or(media.where(teachable: Talk.where(lecture: related_lectures)))
end
# returns array of all those sections from the given sections that belon to
@@ -305,6 +313,7 @@ def editor?
def info_uncached
return email unless name.present?
+
(name_in_tutorials.presence || name) + ' (' + email + ')'
end
@@ -316,6 +325,7 @@ def info
def tutorial_info_uncached
return email unless tutorial_name.present?
+
tutorial_name + ' (' + email + ')'
end
@@ -327,6 +337,7 @@ def tutorial_info
def name_or_email
return name unless name.blank?
+
email
end
@@ -336,6 +347,7 @@ def tutorial_name
def short_info
return email unless name.present?
+
name
end
@@ -405,9 +417,10 @@ def unrelated_courses
# boards not belonging to lectures
def thredded_can_read_messageboards
return Thredded::Messageboard.all if admin?
+
subscribed_forums =
Thredded::Messageboard.where(id: lectures.map(&:forum_id))
- .or(Thredded::Messageboard.where.not(id: Lecture.all.map(&:forum_id)))
+ .or(Thredded::Messageboard.where.not(id: Lecture.all.map(&:forum_id)))
if teacher? || edited_courses.any? || edited_lectures.any?
return Thredded::Messageboard.where(id: teaching_related_lectures
.map(&:forum_id))
@@ -421,6 +434,7 @@ def thredded_can_read_messageboards
# lecture (they are for admins posts only)
def thredded_can_write_messageboards
return Thredded::Messageboard.all if admin?
+
subscribed_forums =
Thredded::Messageboard.where(id: lectures.map(&:forum_id))
if teacher? || edited_courses.any? || edited_lectures.any?
@@ -438,6 +452,7 @@ def thredded_can_write_messageboards
# - none otherwise
def thredded_can_moderate_messageboards
return Thredded::Messageboard.all if admin?
+
if teacher? || edited_courses.any? || edited_lectures.any?
return Thredded::Messageboard.where(id: teaching_related_lectures
.map(&:forum_id))
@@ -464,25 +479,26 @@ def filter_visible_media(media)
nonsubscribed_talks = Talk.where(lecture: nonsubscribed_lectures)
edited_talks = Talk.where(lecture: teaching_related_lectures)
return media if admin
+
media.where(teachable: courses, released: ['all', 'subscribers', 'users'])
- .or(media.where(teachable: nonsubscribed_courses,
- released: ['all', 'users']))
- .or(media.where(teachable: lectures,
- released: ['all', 'subscribers', 'users']))
- .or(media.where(teachable: nonsubscribed_lectures,
- released: ['all', 'users']))
- .or(media.where(teachable: lessons,
- released: ['all', 'subscribers', 'users']))
- .or(media.where(teachable: nonsubscribed_lessons,
- released: ['all', 'users']))
- .or(media.where(teachable: talks,
- released: ['all', 'subscribers', 'users']))
- .or(media.where(teachable: nonsubscribed_talks,
- released: ['all', 'users']))
- .or(media.where(teachable: edited_courses))
- .or(media.where(teachable: teaching_related_lectures))
- .or(media.where(teachable: edited_lessons))
- .or(media.where(teachable: edited_talks))
+ .or(media.where(teachable: nonsubscribed_courses,
+ released: ['all', 'users']))
+ .or(media.where(teachable: lectures,
+ released: ['all', 'subscribers', 'users']))
+ .or(media.where(teachable: nonsubscribed_lectures,
+ released: ['all', 'users']))
+ .or(media.where(teachable: lessons,
+ released: ['all', 'subscribers', 'users']))
+ .or(media.where(teachable: nonsubscribed_lessons,
+ released: ['all', 'users']))
+ .or(media.where(teachable: talks,
+ released: ['all', 'subscribers', 'users']))
+ .or(media.where(teachable: nonsubscribed_talks,
+ released: ['all', 'users']))
+ .or(media.where(teachable: edited_courses))
+ .or(media.where(teachable: teaching_related_lectures))
+ .or(media.where(teachable: edited_lessons))
+ .or(media.where(teachable: edited_talks))
end
def subscribed_commentable_media_with_comments
@@ -496,11 +512,13 @@ def subscribed_commentable_media_with_comments
def media_latest_comments
subscribed_commentable_media_with_comments
- .map { |m| { medium: m,
- thread: m.commontator_thread,
- latest_comment: m.commontator_thread
- .comments.sort_by(&:created_at)
- .last } }
+ .map { |m|
+ { medium: m,
+ thread: m.commontator_thread,
+ latest_comment: m.commontator_thread
+ .comments.sort_by(&:created_at)
+ .last }
+ }
.sort_by { |x| x[:latest_comment].created_at }.reverse
end
@@ -524,8 +542,9 @@ def anonymized_id
def subscribe_lecture!(lecture)
return false unless lecture.is_a?(Lecture)
return false if lecture.in?(lectures)
+
lectures << lecture
-
+
# make sure subscribed_users is updated in media
Sunspot.index! lecture.media
@@ -535,6 +554,7 @@ def subscribe_lecture!(lecture)
def unsubscribe_lecture!(lecture)
return false unless lecture.is_a?(Lecture)
return false unless lecture.in?(lectures)
+
lectures.delete(lecture)
favorite_lectures.delete(lecture)
@@ -555,6 +575,7 @@ def current_subscribable_lectures
unless editor? || teacher?
return current_lectures.published.sort + no_term_lectures.published.sort
end
+
current_lectures.select { |l| l.edited_by?(self) || l.published? }.sort +
no_term_lectures.select { |l| l.edited_by?(self) || l.published? }.sort
end
@@ -667,6 +688,7 @@ def can_edit?(something)
raise 'can_edit? was called with incompatible class'
end
return true if admin
+
in?(something.editors_with_inheritance.to_a)
end
@@ -676,6 +698,7 @@ def speaker?
def layout
return 'administration' if admin_or_editor?
+
'application_no_sidebar'
end
@@ -693,48 +716,49 @@ def generic?
private
- def set_defaults
- self.subscription_type ||= 1
- self.admin ||= false
- self.name ||= email.split('@').first
- self.locale ||= I18n.default_locale.to_s
- end
+ def set_defaults
+ self.subscription_type ||= 1
+ self.admin ||= false
+ self.name ||= email.split('@').first
+ self.locale ||= I18n.default_locale.to_s
+ end
- # sets time for DSGVO consent to current time
- def set_consented_at
- update(consented_at: Time.now)
- end
+ # sets time for DSGVO consent to current time
+ def set_consented_at
+ update(consented_at: Time.now)
+ end
- # returns array of ids of all courses that preced the subscribed courses
- def preceding_course_ids
- courses.all.map { |l| l.preceding_courses.pluck(:id) }.flatten +
- courses.all.pluck(:id)
- end
+ # returns array of ids of all courses that preced the subscribed courses
+ def preceding_course_ids
+ courses.all.map { |l| l.preceding_courses.pluck(:id) }.flatten +
+ courses.all.pluck(:id)
+ end
- def destroy_single_submissions
- Submission.where(id: submissions.select { |s| s.users.count == 1 }
- .map(&:id)).destroy_all
- end
+ def destroy_single_submissions
+ Submission.where(id: submissions.select { |s| s.users.count == 1 }
+ .map(&:id)).destroy_all
+ end
- def archive_email
- splitting = DefaultSetting::PROJECT_EMAIL.split('@')
- "#{splitting.first}-archive-#{id}@#{splitting.second}"
- end
+ def archive_email
+ splitting = DefaultSetting::PROJECT_EMAIL.split('@')
+ "#{splitting.first}-archive-#{id}@#{splitting.second}"
+ end
- def transfer_contributions_to(user)
- return false unless user && user.valid? && user != self
- given_lectures.update_all(teacher_id: user.id)
- EditableUserJoin.where(user: self, editable_type: 'Medium')
- .update_all(user_id: user.id)
- end
+ def transfer_contributions_to(user)
+ return false unless user && user.valid? && user != self
- def archive_user(archive_name)
- User.create(name: archive_name,
- email: archive_email,
- password: SecureRandom.base58(12),
- consents: true,
- consented_at: Time.now,
- confirmed_at: Time.now,
- archived: true)
- end
+ given_lectures.update_all(teacher_id: user.id)
+ EditableUserJoin.where(user: self, editable_type: 'Medium')
+ .update_all(user_id: user.id)
+ end
+
+ def archive_user(archive_name)
+ User.create(name: archive_name,
+ email: archive_email,
+ password: SecureRandom.base58(12),
+ consents: true,
+ consented_at: Time.now,
+ confirmed_at: Time.now,
+ archived: true)
+ end
end
diff --git a/app/models/user_cleaner.rb b/app/models/user_cleaner.rb
index 02a58466b..9c40eecba 100644
--- a/app/models/user_cleaner.rb
+++ b/app/models/user_cleaner.rb
@@ -4,7 +4,8 @@ class UserCleaner
def login
@imap = Net::IMAP.new(ENV['IMAPSERVER'], port: 993, ssl: true)
- @imap.authenticate('LOGIN', ENV['PROJECT_EMAIL_USERNAME'], ENV['PROJECT_EMAIL_PASSWORD'])
+ @imap.authenticate('LOGIN', ENV['PROJECT_EMAIL_USERNAME'],
+ ENV['PROJECT_EMAIL_PASSWORD'])
end
def logout
@@ -16,8 +17,10 @@ def search_emails_and_hashes
@hash_dict = {}
@imap.examine(ENV['PROJECT_EMAIL_MAILBOX'])
# Mails containing multiple email addresses (Subject: "Undelivered Mail Returned to Sender")
- @imap.search(['SUBJECT', 'Undelivered Mail Returned to Sender']).each do |message_id|
- body = @imap.fetch(message_id, "BODY[TEXT]")[0].attr["BODY[TEXT]"].squeeze(" ")
+ @imap.search(['SUBJECT',
+ 'Undelivered Mail Returned to Sender']).each do |message_id|
+ body = @imap.fetch(message_id,
+ "BODY[TEXT]")[0].attr["BODY[TEXT]"].squeeze(" ")
if match = body.scan(/([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})[\s\S]*?([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})[\s\S]*?User has moved to ERROR: Account expired/)
match = match.flatten.uniq
match.each do |email|
@@ -34,8 +37,10 @@ def search_emails_and_hashes
'([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})>[\s\S]*?User unknown in virtual mailbox table'
]
- @imap.search(['SUBJECT', 'Delivery Status Notification (Failure)']).each do |message_id|
- body = @imap.fetch(message_id, "BODY[TEXT]")[0].attr["BODY[TEXT]"].squeeze(" ")
+ @imap.search(['SUBJECT',
+ 'Delivery Status Notification (Failure)']).each do |message_id|
+ body = @imap.fetch(message_id,
+ "BODY[TEXT]")[0].attr["BODY[TEXT]"].squeeze(" ")
patterns.each do |pattern|
if match = body.scan(/#{pattern}/)
match = match.flatten.uniq
@@ -87,10 +92,11 @@ def delete_ghosts
end
end
- def move_mail(message_ids, attempt=0)
+ def move_mail(message_ids, attempt = 0)
return if message_ids.blank?
+
message_ids = Array(message_ids)
- if attempt>3
+ if attempt > 3
return
end
@@ -98,7 +104,7 @@ def move_mail(message_ids, attempt=0)
@imap.examine(ENV['PROJECT_EMAIL_MAILBOX'])
@imap.move(message_ids, "Other Users/mampf/handled_bounces")
rescue Net::IMAP::BadResponseError
- move_mail(message_ids, attempt=attempt+1)
+ move_mail(message_ids, attempt = attempt + 1)
end
end
@@ -106,11 +112,11 @@ def clean!
login
search_emails_and_hashes
return if @email_dict.blank?
+
send_hashes
sleep(10)
search_emails_and_hashes
delete_ghosts
logout
end
-
-end
\ No newline at end of file
+end
diff --git a/app/models/user_submission_join.rb b/app/models/user_submission_join.rb
index d0c6b6d01..9218519c6 100644
--- a/app/models/user_submission_join.rb
+++ b/app/models/user_submission_join.rb
@@ -6,23 +6,26 @@ class UserSubmissionJoin < ApplicationRecord
validate :max_team_size, on: :create
def assignment
- submission.assignment
+ submission.assignment
end
private
- def only_one_per_assignment
- if UserSubmissionJoin.where(user: user, submission: assignment.submissions)
- .none?
- return true
- end
- errors.add(:base, :only_one_per_assignment)
- end
+ def only_one_per_assignment
+ if UserSubmissionJoin.where(user: user,
+ submission: assignment.submissions)
+ .none?
+ return true
+ end
- def max_team_size
- lecture = submission.assignment.lecture
- return true unless lecture.submission_max_team_size
- return true if submission.users.size < lecture.submission_max_team_size
- errors.add(:base, :team_size)
- end
+ errors.add(:base, :only_one_per_assignment)
+ end
+
+ def max_team_size
+ lecture = submission.assignment.lecture
+ return true unless lecture.submission_max_team_size
+ return true if submission.users.size < lecture.submission_max_team_size
+
+ errors.add(:base, :team_size)
+ end
end
diff --git a/app/uploaders/correction_uploader.rb b/app/uploaders/correction_uploader.rb
index a17390266..cc7a30ba3 100644
--- a/app/uploaders/correction_uploader.rb
+++ b/app/uploaders/correction_uploader.rb
@@ -4,6 +4,6 @@
class CorrectionUploader < Shrine
# shrine plugins
plugin :determine_mime_type, analyzer: :marcel
- plugin :upload_endpoint, max_size: 30*1024*1024 # 30 MB
+ plugin :upload_endpoint, max_size: 30 * 1024 * 1024 # 30 MB
plugin :default_storage, cache: :submission_cache, store: :submission_store
end
diff --git a/app/uploaders/geogebra_uploader.rb b/app/uploaders/geogebra_uploader.rb
index 5e11e9977..32fe00ff5 100644
--- a/app/uploaders/geogebra_uploader.rb
+++ b/app/uploaders/geogebra_uploader.rb
@@ -24,4 +24,4 @@ class GeogebraUploader < Shrine
end
{ screenshot: File.open(unzipped) }
end
-end
\ No newline at end of file
+end
diff --git a/app/uploaders/pdf_uploader.rb b/app/uploaders/pdf_uploader.rb
index d75b6add2..bacdb9bcc 100644
--- a/app/uploaders/pdf_uploader.rb
+++ b/app/uploaders/pdf_uploader.rb
@@ -30,14 +30,14 @@ class PdfUploader < Shrine
# extract lines that correspond to MaMpf-Label entries from LaTEX
# package mampf.sty
structure = if File.file?(structure_path)
- open(structure_path, "r") do
- |io| io.read.encode("UTF-8", invalid: :replace)
- end
- end
+ open(structure_path, "r") do |io|
+ io.read.encode("UTF-8", invalid: :replace)
+ end
+ end
structure ||= ''
bookmarks = structure.scan(/MaMpf-Label\|(.*?)\n/).flatten
result = []
- bookmarks.each_with_index do |b,i|
+ bookmarks.each_with_index do |b, i|
# extract bookmark data
# line may look like this:
# defn:erster-Tag|Definition|1.1|Erster Tag|1
diff --git a/app/uploaders/submission_uploader.rb b/app/uploaders/submission_uploader.rb
index 243402594..dd8d4f9e5 100644
--- a/app/uploaders/submission_uploader.rb
+++ b/app/uploaders/submission_uploader.rb
@@ -4,7 +4,7 @@
class SubmissionUploader < Shrine
# shrine plugins
plugin :determine_mime_type, analyzer: :marcel
- plugin :upload_endpoint, max_size: 20*1024*1024 # 20 MB
- plugin :default_storage, cache: :submission_cache, store: :submission_store
- plugin :restore_cached_data
+ plugin :upload_endpoint, max_size: 20 * 1024 * 1024 # 20 MB
+ plugin :default_storage, cache: :submission_cache, store: :submission_store
+ plugin :restore_cached_data
end
diff --git a/app/uploaders/video_uploader.rb b/app/uploaders/video_uploader.rb
index 3613a50fb..4e42b3134 100644
--- a/app/uploaders/video_uploader.rb
+++ b/app/uploaders/video_uploader.rb
@@ -16,8 +16,8 @@ class VideoUploader < Shrine
if options[:action] != :upload
movie = Shrine.with_file(io) { |file| FFMPEG::Movie.new(file.path) }
- { 'duration' => movie.duration,
- 'bitrate' => movie.bitrate,
+ { 'duration' => movie.duration,
+ 'bitrate' => movie.bitrate,
'resolution' => movie.resolution,
'frame_rate' => movie.frame_rate }
end
diff --git a/app/uploaders/vtt_uploader.rb b/app/uploaders/vtt_uploader.rb
index d6cc77163..0e8dfdcce 100644
--- a/app/uploaders/vtt_uploader.rb
+++ b/app/uploaders/vtt_uploader.rb
@@ -2,4 +2,4 @@
class VttUploader < Shrine
plugin :pretty_location
plugin :determine_mime_type
-end
\ No newline at end of file
+end
diff --git a/app/uploaders/zip_uploader.rb b/app/uploaders/zip_uploader.rb
index f2ce1220d..353280167 100644
--- a/app/uploaders/zip_uploader.rb
+++ b/app/uploaders/zip_uploader.rb
@@ -3,15 +3,15 @@ class ZipUploader < Shrine
# shrine plugins
plugin :determine_mime_type, analyzer: :marcel
plugin :validation_helpers
- plugin :upload_endpoint, max_size: 1024*1024*1024 # 1 GB
- plugin :default_storage, cache: :submission_cache, store: :submission_store
+ plugin :upload_endpoint, max_size: 1024 * 1024 * 1024 # 1 GB
+ plugin :default_storage, cache: :submission_cache, store: :submission_store
Attacher.validate do
validate_mime_type_inclusion %w[application/zip],
- message:
- I18n.t('package.no_zip')
- # maximum size of 1 GB
- validate_max_size 1024*1024*1024,
- message: I18n.t('package.too_big')
+ message:
+ I18n.t('package.no_zip')
+ # maximum size of 1 GB
+ validate_max_size 1024 * 1024 * 1024,
+ message: I18n.t('package.too_big')
end
-end
\ No newline at end of file
+end
diff --git a/app/validators/http_url_validator.rb b/app/validators/http_url_validator.rb
index 68806ee14..7dcf6ac83 100644
--- a/app/validators/http_url_validator.rb
+++ b/app/validators/http_url_validator.rb
@@ -1,5 +1,4 @@
class HttpUrlValidator < ActiveModel::EachValidator
-
def self.compliant?(value)
uri = URI.parse(Addressable::URI.encode(value))
uri.is_a?(URI::HTTP) && !uri.host.nil?
diff --git a/app/views/users/list.json.jbuilder b/app/views/users/list.json.jbuilder
index 87cfb45e1..c6df8a8ba 100644
--- a/app/views/users/list.json.jbuilder
+++ b/app/views/users/list.json.jbuilder
@@ -1,4 +1,4 @@
json.array! @users do |user|
json.id user.id
json.text user.tutorial_info
-end
\ No newline at end of file
+end
diff --git a/app/workers/cache_cleaner.rb b/app/workers/cache_cleaner.rb
index 566ddfd47..6b77f4bf4 100644
--- a/app/workers/cache_cleaner.rb
+++ b/app/workers/cache_cleaner.rb
@@ -7,4 +7,4 @@ def perform
submission_cache.clear! { |path| path.mtime < Time.now - 1.week }
media_cache.clear! { |path| path.mtime < Time.now - 1.week }
end
-end
\ No newline at end of file
+end
diff --git a/app/workers/consumption_saver.rb b/app/workers/consumption_saver.rb
index ca1d9add6..924772b77 100644
--- a/app/workers/consumption_saver.rb
+++ b/app/workers/consumption_saver.rb
@@ -6,4 +6,4 @@ def perform(medium_id, mode, sort)
mode: mode,
sort: sort)
end
-end
\ No newline at end of file
+end
diff --git a/app/workers/interaction_saver.rb b/app/workers/interaction_saver.rb
index 05fa6b36f..ec89207ad 100644
--- a/app/workers/interaction_saver.rb
+++ b/app/workers/interaction_saver.rb
@@ -3,12 +3,12 @@ class InteractionSaver
def perform(session_id, full_path, referrer, study_participant)
referrer_url = if referrer.to_s.include?(ENV['URL_HOST'])
- referrer.to_s.remove(ENV['URL_HOST'])
- .remove('https://').remove('http://')
- end
+ referrer.to_s.remove(ENV['URL_HOST'])
+ .remove('https://').remove('http://')
+ end
Interaction.create(session_id: Digest::SHA2.hexdigest(session_id).first(10),
full_path: full_path,
referrer_url: referrer_url,
study_participant: study_participant)
end
-end
\ No newline at end of file
+end
diff --git a/app/workers/media_publisher.rb b/app/workers/media_publisher.rb
index e847da8b3..17318e427 100644
--- a/app/workers/media_publisher.rb
+++ b/app/workers/media_publisher.rb
@@ -7,4 +7,4 @@ def perform
.map(&:medium_id)
Medium.where(id: media_ids).each(&:publish!)
end
-end
\ No newline at end of file
+end
diff --git a/app/workers/metadata_extractor.rb b/app/workers/metadata_extractor.rb
index 428ecfb9f..08384735b 100644
--- a/app/workers/metadata_extractor.rb
+++ b/app/workers/metadata_extractor.rb
@@ -4,8 +4,9 @@ class MetadataExtractor
def perform(medium_id)
medium = Medium.find(medium_id)
return unless medium && medium.video.present?
+
medium.video.refresh_metadata!(action: :store)
refreshed_video = medium.video
medium.update(video_data: refreshed_video.to_json)
end
-end
\ No newline at end of file
+end
diff --git a/app/workers/probe_saver.rb b/app/workers/probe_saver.rb
index 83a86c09c..553f5399e 100644
--- a/app/workers/probe_saver.rb
+++ b/app/workers/probe_saver.rb
@@ -12,7 +12,8 @@ def perform(quiz_id, question_id, remark_id, correct, progress, session_id,
study_participant: study_participant,
input: input)
return unless progress == -1
+
success = Probe.where(session_id: session_id, correct: true).count
probe.update(success: success)
end
-end
\ No newline at end of file
+end
diff --git a/app/workers/submissions_cleaner.rb b/app/workers/submissions_cleaner.rb
index e5660eb1f..14bebf6ed 100644
--- a/app/workers/submissions_cleaner.rb
+++ b/app/workers/submissions_cleaner.rb
@@ -5,4 +5,4 @@ def perform
submission_cleaner = SubmissionCleaner.new(date: Time.zone.today)
submission_cleaner.clean!
end
-end
\ No newline at end of file
+end
diff --git a/app/workers/user_cleaner_job.rb b/app/workers/user_cleaner_job.rb
index d64a651bf..4c0187a89 100644
--- a/app/workers/user_cleaner_job.rb
+++ b/app/workers/user_cleaner_job.rb
@@ -5,4 +5,4 @@ def perform
user_cleaner = UserCleaner.new()
user_cleaner.clean!
end
-end
\ No newline at end of file
+end
From 1982f2875184823f1657cf53a74615b0ab2973ff Mon Sep 17 00:00:00 2001
From: Splines <37160523+Splines@users.noreply.github.com>
Date: Thu, 11 May 2023 18:45:32 +0200
Subject: [PATCH 13/22] Fix scope of .new-comment CSS class (#499)
---
app/assets/stylesheets/navbar.scss | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/app/assets/stylesheets/navbar.scss b/app/assets/stylesheets/navbar.scss
index 282060bcf..18bd50825 100644
--- a/app/assets/stylesheets/navbar.scss
+++ b/app/assets/stylesheets/navbar.scss
@@ -19,6 +19,10 @@
.navbar {
box-shadow: 1px 4px 7px -2px rgba(0, 0, 0, 0.1);
z-index: 1000; // place navbar and its shadow on top of everything
+
+ .new-comment {
+ color: #ffc107 !important;
+ }
}
#navbar-buttons a {
@@ -36,8 +40,4 @@
left: 16px;
}
}
-}
-
-.new-comment {
- color: #ffc107 !important;
}
\ No newline at end of file
From 3fc077fb973bc5cce0e66f4264e0db761a4019be Mon Sep 17 00:00:00 2001
From: Splines <37160523+Splines@users.noreply.github.com>
Date: Mon, 15 May 2023 14:59:32 +0200
Subject: [PATCH 14/22] Fix ghost links in nested tabs (#500)
* Fix ghost links in nested tabs
* Fix spacing in media card
---
app/assets/stylesheets/media.scss | 15 ----
app/views/lectures/edit/_media.html.erb | 8 +-
app/views/media/_table_column.html.erb | 113 ++++++++++++------------
3 files changed, 62 insertions(+), 74 deletions(-)
diff --git a/app/assets/stylesheets/media.scss b/app/assets/stylesheets/media.scss
index 97d707e52..938a0ec7e 100644
--- a/app/assets/stylesheets/media.scss
+++ b/app/assets/stylesheets/media.scss
@@ -315,21 +315,6 @@
text-decoration: none;
}
-.tab-content {
- display: flex;
-}
-
-.tab-content > .tab-pane {
- display: block; /* undo "display: none;" */
- visibility: hidden;
- margin-right: -100%;
- width: 100%;
-}
-
-.tab-content > .active {
- visibility: visible;
-}
-
.break-text-any-where {
word-break: break-all;
}
\ No newline at end of file
diff --git a/app/views/lectures/edit/_media.html.erb b/app/views/lectures/edit/_media.html.erb
index 8f2ec846f..2d2bedf47 100644
--- a/app/views/lectures/edit/_media.html.erb
+++ b/app/views/lectures/edit/_media.html.erb
@@ -29,12 +29,12 @@
-
+
-
+
<% media_sorts.each do |s| %>