forked from autolab/Autolab
-
Notifications
You must be signed in to change notification settings - Fork 0
/
groups_controller.rb
304 lines (274 loc) · 9.68 KB
/
groups_controller.rb
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
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
class GroupsController < ApplicationController
# inherited from ApplicationController
before_action :set_assessment
before_action :check_assessment_for_groups
before_action :set_group, only: [:show, :edit, :update, :destroy, :add, :join, :leave]
respond_to :html
rescue_from ActionView::MissingTemplate do |exception|
redirect_to("/home/error_404")
end
##
# can be used by instructors to check groups. Students get redirected,
# either to action: :new or to their group page.
#
action_auth_level :index, :student
def index
unless @cud.instructor
aud = @assessment.aud_for @cud.id
if aud.group
redirect_to([@course, @assessment, aud.group]) && return
else
redirect_to(action: :new) && return
end
end
@groups = @assessment.groups
@groupAssessments = @course.assessments
.where("`group_size` > 1 AND `group_size` <= ?", @assessment.group_size).where.not(id: @assessment.id)
@grouplessCUDs = @assessment.grouplessCUDs
respond_with(@course, @assessment, @groups)
end
##
# instructors can use this to view groups, and students can view
# their own group with it as well
#
action_auth_level :show, :student
def show
@aud = @assessment.aud_for @cud.id
unless @cud.instructor
if @aud.group_id.nil?
redirect_to(action: :new) && return
elsif @aud.group_id != params[:id].to_i
redirect_to([@course, @assessment, @aud.group]) && return
end
end
if @group.size < @assessment.group_size && @group.is_member(@aud)
@grouplessCUDs = @assessment.grouplessCUDs
end
respond_with(@course, @assessment, @group)
end
##
# lets users create new groups. students with groups get redirected.
#
action_auth_level :new, :student
def new
aud = @assessment.aud_for(@cud)
unless @cud.instructor
redirect_to([@course, @assessment, aud.group]) && return if aud.group
end
@group = Group.new
@grouplessCUDs = @assessment.grouplessCUDs
@unfullGroups = @assessment.groups.all.select { |g| g.assessment_user_data.size < @assessment.group_size }
respond_with(@course, @assessment, @group)
end
##
# Given a member_id or member_email (id taking precidence), this creates
# a new group, with @cud being confirmed and the member being GROUP_CONFIRMED
#
action_auth_level :create, :student
def create
unless cud2 = get_member_cud
redirect_to(action: :new) && return
end
aud1 = @assessment.aud_for @cud.id
aud2 = @assessment.aud_for cud2.id
if aud1.group_confirmed(AssessmentUserDatum::MEMBER_CONFIRMED)
flash[:error] = "You have already selected a group."
redirect_to(action: :new) && return
elsif aud2.group_confirmed(AssessmentUserDatum::MEMBER_CONFIRMED)
flash[:error] = cud2.email + " has already selected a group."
redirect_to(action: :new) && return
end
group = Group.new
group.name = params[:group_name] || "Untitled"
ActiveRecord::Base.transaction do
group.save! # save now so the group gets an id
aud1.group_id = group.id
aud1.membership_status = AssessmentUserDatum::CONFIRMED
aud1.save!
aud2.group_id = group.id
aud2.membership_status = AssessmentUserDatum::GROUP_CONFIRMED
aud2.save!
end
flash[:success] = "Group Created!"
respond_with(@course, @assessment, group)
end
##
# this is used to update the name of the given group
#
action_auth_level :update, :student
def update
if params[:group]
aud = @assessment.aud_for @cud.id
if @group.is_member(aud) || @cud.instructor
flash[:notice] = "Group was successfully updated." if @group.update(group_params)
end
end
respond_with(@course, @assessment, @group)
end
##
# instructors can use this to disband a group. No CUDs are harmed
#
action_auth_level :destroy, :instructor
def destroy
ActiveRecord::Base.transaction do
@group.assessment_user_data.each do |aud|
aud.group_id = nil
aud.membership_status = AssessmentUserDatum::UNCONFIRMED
aud.save!
end
@group.destroy!
end
respond_with(@course, @assessment, @group)
end
##
# attempts to copy the groups from the assessment with importFrom as the id.
# it will leave currently created groups untouched, and won't work if importFrom
# has larger groups than this assessment, or no groups at all
#
action_auth_level :import, :instructor
def import
ass = @course.assessments.find(params[:ass])
if !ass
flash[:error] = "Assessment not found."
redirect_to(action: :index) && return
elsif !ass.has_groups? || ass.group_size > @assessment.group_size || @assessment.id == ass.id
flash[:error] = "That assessment cannot be imported."
redirect_to(action: :index) && return
end
ass.groups.each do |g|
group = Group.new
group.name = g.name
count = 0
g.assessment_user_data.each do |a|
cud = a.course_user_datum
aud = @assessment.aud_for cud.id
if aud.group_confirmed(AssessmentUserDatum::UNCONFIRMED)
aud.group = group
aud.membership_status = a.membership_status
count += 1 if aud.save!
end
end
group.save! if count > 0
end
flash[:success] = "Groups Successfully Imported"
redirect_to(action: :index) && return
end
##
# add is when a group adds a student to itself.
# the student will need to confirm membership with a call to join.
#
# member_id - the id of the member to be added
#
action_auth_level :add, :student
def add
unless @group.is_member(@assessment.aud_for(@cud.id)) || @cud.instructor
redirect_to([@course, @assessment, :groups]) && return
end
unless cud = get_member_cud
redirect_to([@course, @assessment, @group]) && return
end
newMemberAUD = @assessment.aud_for cud.id
# if we're adding a new member, and not group-confirming someone, make sure that the group is not too large
unless @group.enough_room_for(newMemberAUD, @assessment.group_size)
flash[:error] = "This group is at the maximum size for this assessment."
redirect_to([@course, @assessment, :groups]) && return
end
# if the new member has no previous group or was already in this group, group-confirm the new member
if newMemberAUD.membership_status == AssessmentUserDatum::UNCONFIRMED || newMemberAUD.group_id == @group.id
newMemberAUD.group = @group
newMemberAUD.membership_status |= AssessmentUserDatum::GROUP_CONFIRMED
newMemberAUD.save!
flash[:success] = "Group confirmed!"
end
respond_with(@course, @assessment, @group)
end
##
# join is when a student asks to join a group.
# a group-confirmed member of the group will need to confirm membership
# with a call to add.
#
action_auth_level :join, :student
def join
newMemberAUD = @assessment.aud_for(@cud.id)
# make sure that the group is not too large
unless @group.enough_room_for(newMemberAUD, @assessment.group_size)
flash[:error] = "This group is at the maximum size for this assessment"
redirect_to([@course, @assessment, :groups]) && return
end
# if the new member has no previous group or was already in this group, group-confirm the new member
if newMemberAUD.membership_status == AssessmentUserDatum::UNCONFIRMED || newMemberAUD.group_id == @group.id
newMemberAUD.group = @group
newMemberAUD.membership_status |= AssessmentUserDatum::MEMBER_CONFIRMED
newMemberAUD.save!
flash[:success] = "Membership confirmed!"
end
respond_with(@course, @assessment, @group)
end
##
# leave will clear a student's membership status with a group
# students can always leave their own group, and groups can remove
# a group-confirmed, but not member-confirmed, student
#
# member_id - the id of the member, or @cud.id if not present
#
action_auth_level :leave, :student
def leave
cud = get_member_cud
if cud
leaver = @assessment.aud_for(cud.id)
booter = @assessment.aud_for(@cud.id)
if @group.is_member(booter) && leaver.group_id == @group.id &&
leaver.membership_status != AssessmentUserDatum::CONFIRMED
leaver.group = nil
leaver.membership_status = AssessmentUserDatum::UNCONFIRMED
leaver.save!
end
else
leaver = @assessment.aud_for(@cud.id)
unless leaver.group_id == @group.id
redirect_to([@course, @assessment, @group]) && return
end
leaver.group = nil
leaver.membership_status = AssessmentUserDatum::UNCONFIRMED
ActiveRecord::Base.transaction do
leaver.save!
@group.destroy! if @group.assessment_user_data.size == 0
end
end
respond_with(@course, @assessment, @group)
end
private
def check_assessment_for_groups
unless @assessment.has_groups?
flash[:error] = "This is a solo assessment."
redirect_to([@course, @assessment]) && return
end
end
def set_group
@group = Group.find(params[:id])
end
def group_params
params.require(:group).permit(:name)
end
##
# returns the cud whose status in the group is being affected
# or nil if something is amiss. Will set flash[:error] in that case
#
def get_member_cud
cud = if params[:member_id]
@course.course_user_data.find(params[:member_id].to_i)
elsif params[:member_email]
@course.course_user_data.joins(:user).find_by(users: { email: params[:member_email] })
else
nil
end
if !cud
flash[:error] = "The given student was not found in this course."
return nil
elsif @cud.id == cud.id
flash[:error] = "You can't create a group with just yourself."
return nil
end
cud
end
end