-
Notifications
You must be signed in to change notification settings - Fork 42
Expand file tree
/
Copy pathcourses_controller.rb
More file actions
232 lines (196 loc) · 7.79 KB
/
Copy pathcourses_controller.rb
File metadata and controls
232 lines (196 loc) · 7.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
require 'course_refresher'
require 'natsort'
require 'course_list'
require 'exercise_completion_status_generator'
class CoursesController < ApplicationController
include PointVisualisation
before_action :set_organization
before_action :set_course, except: [:help, :index, :show_json]
skip_authorization_check only: [:index]
def index
ordering = 'hidden, disabled_status, LOWER(name)'
respond_to do |format|
format.html do
redirect_to organization_path(@organization)
end
format.json do
courses = @organization.courses.ongoing.order(ordering)
courses = courses.select { |c| c.visible_to?(current_user) }
authorize! :read, courses
return respond_access_denied('Authentication required') if current_user.guest?
opts = {include_points: !!params[:show_points], include_unlock_conditions: !!params[:show_unlock_conditions]}
data = {
api_version: ApiVersion::API_VERSION,
courses: CourseList.new(current_user, view_context).course_list_data(@organization, courses, opts)
}
render json: data.to_json
end
end
end
def show
if session[:refresh_report]
@refresh_report = session[:refresh_report]
session.delete(:refresh_report)
end
authorize! :read, @course
UncomputedUnlock.resolve(@course, current_user)
define_point_stats(current_user)
respond_to do |format|
format.html do
assign_show_view_vars
add_course_breadcrumb
end
format.json do
return respond_access_denied('Authentication required') if current_user.guest?
opts = {include_points: !!params[:show_points], include_unlock_conditions: !!params[:show_unlock_conditions]}
data = {
api_version: ApiVersion::API_VERSION,
course: CourseInfo.new(current_user, view_context).course_data(@organization, @course, opts)
}
render json: data.to_json
end
end
end
# Method for teacher to give a single course for students to select.
def show_json
course = [Course.find(params[:id])]
authorize! :read, course
return respond_access_denied('Authentication required') if current_user.guest?
data = {
api_version: ApiVersion::API_VERSION,
courses: CourseList.new(current_user, view_context).course_list_data(@organization, course)
}
render json: data.to_json
end
def refresh
authorize! :refresh, @course
refresh_course(@course)
redirect_to organization_course_path
end
def enable
authorize! :teach, @organization # should assistants be able to enable/disable?
@course.enabled!
redirect_to(organization_course_path(@organization, @course), notice: 'Course was successfully enabled.')
end
def disable
authorize! :teach, @organization
@course.disabled!
redirect_to(organization_course_path(@organization, @course), notice: 'Course was successfully disabled.')
end
def toggle_hidden
authorize! :teach, @organization
@course.update!(hidden: !@course.hidden)
redirect_to(organization_course_path(@organization, @course), notice: "Course is now #{@course.hidden? ? 'hidden' : 'visible'}.")
end
def manage_deadlines
authorize! :manage_deadlines, @course
add_course_breadcrumb
add_breadcrumb 'Manage deadlines'
assign_show_view_vars
end
def save_deadlines
authorize! :manage_deadlines, @course
groups = group_params
groups.each do |name, deadlines|
soft_deadlines = [deadlines[:soft][:static], deadlines[:soft][:unlock]].to_json
hard_deadlines = [deadlines[:hard][:static], deadlines[:hard][:unlock]].to_json
@course.exercise_group_by_name(name).soft_group_deadline = soft_deadlines
@course.exercise_group_by_name(name).hard_group_deadline = hard_deadlines
end
exercises = params[:exercise] || {}
exercises.each do |name, deadlines|
soft_deadlines = [deadlines[:soft][:static], deadlines[:soft][:unlock]].to_json
hard_deadlines = [deadlines[:hard][:static], deadlines[:hard][:unlock]].to_json
exercise = Exercise.where(course_id: @course.id).find_by(name: name)
unless exercise.nil?
exercise.soft_deadline_spec = soft_deadlines
exercise.deadline_spec = hard_deadlines
exercise.save!
end
end
redirect_to manage_deadlines_organization_course_path(@organization, @course), notice: 'Successfully saved deadlines.'
rescue DeadlineSpec::InvalidSyntaxError => e
redirect_to manage_deadlines_organization_course_path(@organization, @course), alert: e.to_s
end
def help
@course = Course.find(params[:course_id])
authorize! :read, @course
add_course_breadcrumb
add_breadcrumb 'Help page'
end
def manage_unlocks
authorize! :manage_unlocks, @course
add_course_breadcrumb
add_breadcrumb 'Manage unlocks'
assign_show_view_vars
end
def save_unlocks
authorize! :manage_unlocks, @course
groups = group_params
groups.each do |name, conditions|
array = conditions.values.reject(&:blank?)
@course.exercise_group_by_name(name).group_unlock_conditions = array.to_json
UncomputedUnlock.create_all_for_course(@course)
end
redirect_to manage_unlocks_organization_course_path, notice: 'Successfully set unlock dates.'
rescue UnlockSpec::InvalidSyntaxError => e
redirect_to manage_unlocks_organization_course_path(@organization, @course), alert: e.to_s
end
def manage_exercises
authorize! :manage_exercises, @course
add_course_breadcrumb
add_breadcrumb 'Manage exercises'
@exercises = @course.exercises.natsort_by(&:name)
@exercises_id_map = @exercises.map { |e| [e.id, e] }.to_h
end
def toggle_submission_result_visibility
authorize! :toggle_submission_result_visibility, @course
@course.toggle_submission_result_visiblity
redirect_to organization_course_path(@organization, @course), notice: "Submission results are now #{@course.hide_submission_results ? 'hidden' : 'visible'}"
end
private
def course_params
if @course.custom?
params.require(:course).permit(:title, :description, :material_url, :source_url, :git_branch, :external_scoreboard_url)
else
params.require(:course).permit(:title, :description, :material_url, :external_scoreboard_url)
end
end
def assign_show_view_vars
@exercises = @course.exercises.includes(:course)
@exercises.preload(:unlocks).where(unlocks: { user: current_user })
@exercises = @exercises.select { |ex| ex.visible_to?(current_user) }
.natsort_by(&:name)
@exercise_completion_status = ExerciseCompletionStatusGenerator.completion_status(current_user, @course)
@unlocks = current_user.unlocks.where(course: @course).where('valid_after IS NULL OR valid_after < ?', Time.zone.now).pluck(:exercise_name)
unless current_user.guest?
max_submissions = 100
@submissions = @course.submissions
@submissions = @submissions.where(user_id: current_user.id) unless can? :teach, @course
@submissions = @submissions.order('created_at DESC').includes(:user)
@total_submissions = @submissions.where.not(user: User.non_legitimate_students).count
@submissions = @submissions.limit(max_submissions)
Submission.eager_load_exercises(@submissions)
end
end
def set_organization
@organization = Organization.find_by!(slug: params[:organization_id])
end
def set_course
@course = Course.find(params[:id])
end
def group_params
sliced = params.slice(:group, :empty_group)
groups = sliced[:group] || {}
empty_group = sliced[:empty_group] || {}
groups[''] = empty_group unless empty_group.empty?
groups
end
def refresh_course(course, options = {})
begin
session[:refresh_report] = course.refresh(options)
rescue CourseRefresher::Failure => e
session[:refresh_report] = e.report
end
end
end