Description:
fix bug with duplicate logins are given also increase dropdown size on group view
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r809:e8c8ed4696af - - 3 files changed: 7 inserted, 3 deleted

@@ -1,20 +1,20
1 class Group < ActiveRecord::Base
1 class Group < ActiveRecord::Base
2 has_many :groups_problems, class_name: 'GroupProblem'
2 has_many :groups_problems, class_name: 'GroupProblem'
3 has_many :problems, :through => :groups_problems
3 has_many :problems, :through => :groups_problems
4
4
5 has_many :groups_users, class_name: 'GroupUser'
5 has_many :groups_users, class_name: 'GroupUser'
6 has_many :users, :through => :groups_users
6 has_many :users, :through => :groups_users
7
7
8 #has_and_belongs_to_many :problems
8 #has_and_belongs_to_many :problems
9 #has_and_belongs_to_many :users
9 #has_and_belongs_to_many :users
10
10
11 def add_users_skip_existing(users_list)
11 def add_users_skip_existing(users_list)
12 new_list = []
12 new_list = []
13 - users_list.each do |u|
13 + users_list.uniq.each do |u|
14 new_list << u unless users.include? u
14 new_list << u unless users.include? u
15 end
15 end
16 users << new_list
16 users << new_list
17 end
17 end
18
18
19 end
19 end
20
20
@@ -1,457 +1,461
1 require 'digest/sha1'
1 require 'digest/sha1'
2 require 'net/pop'
2 require 'net/pop'
3 require 'net/https'
3 require 'net/https'
4 require 'net/http'
4 require 'net/http'
5 require 'json'
5 require 'json'
6
6
7 class User < ActiveRecord::Base
7 class User < ActiveRecord::Base
8
8
9 has_and_belongs_to_many :roles
9 has_and_belongs_to_many :roles
10
10
11 #has_and_belongs_to_many :groups
11 #has_and_belongs_to_many :groups
12 has_many :groups_users, class_name: 'GroupUser'
12 has_many :groups_users, class_name: 'GroupUser'
13 has_many :groups, :through => :groups_users
13 has_many :groups, :through => :groups_users
14
14
15 has_many :test_requests, -> {order(submitted_at: :desc)}
15 has_many :test_requests, -> {order(submitted_at: :desc)}
16
16
17 has_many :messages, -> { order(created_at: :desc) },
17 has_many :messages, -> { order(created_at: :desc) },
18 :class_name => "Message",
18 :class_name => "Message",
19 :foreign_key => "sender_id"
19 :foreign_key => "sender_id"
20
20
21 has_many :replied_messages, -> { order(created_at: :desc) },
21 has_many :replied_messages, -> { order(created_at: :desc) },
22 :class_name => "Message",
22 :class_name => "Message",
23 :foreign_key => "receiver_id"
23 :foreign_key => "receiver_id"
24
24
25 has_many :logins
25 has_many :logins
26
26
27 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
27 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
28
28
29 belongs_to :site
29 belongs_to :site
30 belongs_to :country
30 belongs_to :country
31
31
32 has_and_belongs_to_many :contests, -> { order(:name)}
32 has_and_belongs_to_many :contests, -> { order(:name)}
33
33
34 scope :activated_users, -> {where activated: true}
34 scope :activated_users, -> {where activated: true}
35
35
36 validates_presence_of :login
36 validates_presence_of :login
37 validates_uniqueness_of :login
37 validates_uniqueness_of :login
38 validates_format_of :login, :with => /\A[\_A-Za-z0-9]+\z/
38 validates_format_of :login, :with => /\A[\_A-Za-z0-9]+\z/
39 validates_length_of :login, :within => 3..30
39 validates_length_of :login, :within => 3..30
40
40
41 validates_presence_of :full_name
41 validates_presence_of :full_name
42 validates_length_of :full_name, :minimum => 1
42 validates_length_of :full_name, :minimum => 1
43
43
44 validates_presence_of :password, :if => :password_required?
44 validates_presence_of :password, :if => :password_required?
45 validates_length_of :password, :within => 4..50, :if => :password_required?
45 validates_length_of :password, :within => 4..50, :if => :password_required?
46 validates_confirmation_of :password, :if => :password_required?
46 validates_confirmation_of :password, :if => :password_required?
47
47
48 validates_format_of :email,
48 validates_format_of :email,
49 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
49 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
50 :if => :email_validation?
50 :if => :email_validation?
51 validate :uniqueness_of_email_from_activated_users,
51 validate :uniqueness_of_email_from_activated_users,
52 :if => :email_validation?
52 :if => :email_validation?
53 validate :enough_time_interval_between_same_email_registrations,
53 validate :enough_time_interval_between_same_email_registrations,
54 :if => :email_validation?
54 :if => :email_validation?
55
55
56 # these are for ytopc
56 # these are for ytopc
57 # disable for now
57 # disable for now
58 #validates_presence_of :province
58 #validates_presence_of :province
59
59
60 attr_accessor :password
60 attr_accessor :password
61
61
62 before_save :encrypt_new_password
62 before_save :encrypt_new_password
63 before_save :assign_default_site
63 before_save :assign_default_site
64 before_save :assign_default_contest
64 before_save :assign_default_contest
65
65
66 # this is for will_paginate
66 # this is for will_paginate
67 cattr_reader :per_page
67 cattr_reader :per_page
68 @@per_page = 50
68 @@per_page = 50
69
69
70 def self.authenticate(login, password)
70 def self.authenticate(login, password)
71 user = find_by_login(login)
71 user = find_by_login(login)
72 if user
72 if user
73 return user if user.authenticated?(password)
73 return user if user.authenticated?(password)
74 end
74 end
75 end
75 end
76
76
77 def authenticated?(password)
77 def authenticated?(password)
78 if self.activated
78 if self.activated
79 hashed_password == User.encrypt(password,self.salt)
79 hashed_password == User.encrypt(password,self.salt)
80 else
80 else
81 false
81 false
82 end
82 end
83 end
83 end
84
84
85 + def login_with_name
86 + "[#{login}] #{full_name}"
87 + end
88 +
85 def admin?
89 def admin?
86 has_role?('admin')
90 has_role?('admin')
87 end
91 end
88
92
89 def has_role?(role)
93 def has_role?(role)
90 self.roles.where(name: role).count > 0
94 self.roles.where(name: role).count > 0
91 end
95 end
92
96
93 def email_for_editing
97 def email_for_editing
94 if self.email==nil
98 if self.email==nil
95 "(unknown)"
99 "(unknown)"
96 elsif self.email==''
100 elsif self.email==''
97 "(blank)"
101 "(blank)"
98 else
102 else
99 self.email
103 self.email
100 end
104 end
101 end
105 end
102
106
103 def email_for_editing=(e)
107 def email_for_editing=(e)
104 self.email=e
108 self.email=e
105 end
109 end
106
110
107 def alias_for_editing
111 def alias_for_editing
108 if self.alias==nil
112 if self.alias==nil
109 "(unknown)"
113 "(unknown)"
110 elsif self.alias==''
114 elsif self.alias==''
111 "(blank)"
115 "(blank)"
112 else
116 else
113 self.alias
117 self.alias
114 end
118 end
115 end
119 end
116
120
117 def alias_for_editing=(e)
121 def alias_for_editing=(e)
118 self.alias=e
122 self.alias=e
119 end
123 end
120
124
121 def activation_key
125 def activation_key
122 if self.hashed_password==nil
126 if self.hashed_password==nil
123 encrypt_new_password
127 encrypt_new_password
124 end
128 end
125 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
129 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
126 end
130 end
127
131
128 def verify_activation_key(key)
132 def verify_activation_key(key)
129 key == activation_key
133 key == activation_key
130 end
134 end
131
135
132 def self.random_password(length=5)
136 def self.random_password(length=5)
133 chars = 'abcdefghjkmnopqrstuvwxyz'
137 chars = 'abcdefghjkmnopqrstuvwxyz'
134 password = ''
138 password = ''
135 length.times { password << chars[rand(chars.length - 1)] }
139 length.times { password << chars[rand(chars.length - 1)] }
136 password
140 password
137 end
141 end
138
142
139
143
140 # Contest information
144 # Contest information
141
145
142 def self.find_users_with_no_contest()
146 def self.find_users_with_no_contest()
143 users = User.all
147 users = User.all
144 return users.find_all { |u| u.contests.length == 0 }
148 return users.find_all { |u| u.contests.length == 0 }
145 end
149 end
146
150
147
151
148 def contest_time_left
152 def contest_time_left
149 if GraderConfiguration.contest_mode?
153 if GraderConfiguration.contest_mode?
150 return nil if site==nil
154 return nil if site==nil
151 return site.time_left
155 return site.time_left
152 elsif GraderConfiguration.indv_contest_mode?
156 elsif GraderConfiguration.indv_contest_mode?
153 time_limit = GraderConfiguration.contest_time_limit
157 time_limit = GraderConfiguration.contest_time_limit
154 if time_limit == nil
158 if time_limit == nil
155 return nil
159 return nil
156 end
160 end
157 if contest_stat==nil or contest_stat.started_at==nil
161 if contest_stat==nil or contest_stat.started_at==nil
158 return (Time.now.gmtime + time_limit) - Time.now.gmtime
162 return (Time.now.gmtime + time_limit) - Time.now.gmtime
159 else
163 else
160 finish_time = contest_stat.started_at + time_limit
164 finish_time = contest_stat.started_at + time_limit
161 current_time = Time.now.gmtime
165 current_time = Time.now.gmtime
162 if current_time > finish_time
166 if current_time > finish_time
163 return 0
167 return 0
164 else
168 else
165 return finish_time - current_time
169 return finish_time - current_time
166 end
170 end
167 end
171 end
168 else
172 else
169 return nil
173 return nil
170 end
174 end
171 end
175 end
172
176
173 def contest_finished?
177 def contest_finished?
174 if GraderConfiguration.contest_mode?
178 if GraderConfiguration.contest_mode?
175 return false if site==nil
179 return false if site==nil
176 return site.finished?
180 return site.finished?
177 elsif GraderConfiguration.indv_contest_mode?
181 elsif GraderConfiguration.indv_contest_mode?
178 return false if self.contest_stat==nil
182 return false if self.contest_stat==nil
179 return contest_time_left == 0
183 return contest_time_left == 0
180 else
184 else
181 return false
185 return false
182 end
186 end
183 end
187 end
184
188
185 def contest_started?
189 def contest_started?
186 if GraderConfiguration.indv_contest_mode?
190 if GraderConfiguration.indv_contest_mode?
187 stat = self.contest_stat
191 stat = self.contest_stat
188 return ((stat != nil) and (stat.started_at != nil))
192 return ((stat != nil) and (stat.started_at != nil))
189 elsif GraderConfiguration.contest_mode?
193 elsif GraderConfiguration.contest_mode?
190 return true if site==nil
194 return true if site==nil
191 return site.started
195 return site.started
192 else
196 else
193 return true
197 return true
194 end
198 end
195 end
199 end
196
200
197 def update_start_time
201 def update_start_time
198 stat = self.contest_stat
202 stat = self.contest_stat
199 if stat.nil? or stat.started_at.nil?
203 if stat.nil? or stat.started_at.nil?
200 stat ||= UserContestStat.new(:user => self)
204 stat ||= UserContestStat.new(:user => self)
201 stat.started_at = Time.now.gmtime
205 stat.started_at = Time.now.gmtime
202 stat.save
206 stat.save
203 end
207 end
204 end
208 end
205
209
206 def problem_in_user_contests?(problem)
210 def problem_in_user_contests?(problem)
207 problem_contests = problem.contests.all
211 problem_contests = problem.contests.all
208
212
209 if problem_contests.length == 0 # this is public contest
213 if problem_contests.length == 0 # this is public contest
210 return true
214 return true
211 end
215 end
212
216
213 contests.each do |contest|
217 contests.each do |contest|
214 if problem_contests.find {|c| c.id == contest.id }
218 if problem_contests.find {|c| c.id == contest.id }
215 return true
219 return true
216 end
220 end
217 end
221 end
218 return false
222 return false
219 end
223 end
220
224
221 def available_problems_group_by_contests
225 def available_problems_group_by_contests
222 contest_problems = []
226 contest_problems = []
223 pin = {}
227 pin = {}
224 contests.enabled.each do |contest|
228 contests.enabled.each do |contest|
225 available_problems = contest.problems.available
229 available_problems = contest.problems.available
226 contest_problems << {
230 contest_problems << {
227 :contest => contest,
231 :contest => contest,
228 :problems => available_problems
232 :problems => available_problems
229 }
233 }
230 available_problems.each {|p| pin[p.id] = true}
234 available_problems.each {|p| pin[p.id] = true}
231 end
235 end
232 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
236 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
233 contest_problems << {
237 contest_problems << {
234 :contest => nil,
238 :contest => nil,
235 :problems => other_avaiable_problems
239 :problems => other_avaiable_problems
236 }
240 }
237 return contest_problems
241 return contest_problems
238 end
242 end
239
243
240 def solve_all_available_problems?
244 def solve_all_available_problems?
241 available_problems.each do |p|
245 available_problems.each do |p|
242 u = self
246 u = self
243 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
247 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
244 return false if !p or !sub or sub.points < p.full_score
248 return false if !p or !sub or sub.points < p.full_score
245 end
249 end
246 return true
250 return true
247 end
251 end
248
252
249 #get a list of available problem
253 #get a list of available problem
250 def available_problems
254 def available_problems
251 # first, we check if this is normal mode
255 # first, we check if this is normal mode
252 if not GraderConfiguration.multicontests?
256 if not GraderConfiguration.multicontests?
253
257
254 #if this is a normal mode
258 #if this is a normal mode
255 #we show problem based on problem_group, if the config said so
259 #we show problem based on problem_group, if the config said so
256 if GraderConfiguration.use_problem_group?
260 if GraderConfiguration.use_problem_group?
257 return available_problems_in_group
261 return available_problems_in_group
258 else
262 else
259 return Problem.available_problems
263 return Problem.available_problems
260 end
264 end
261 else
265 else
262 #this is multi contest mode
266 #this is multi contest mode
263 contest_problems = []
267 contest_problems = []
264 pin = {}
268 pin = {}
265 contests.enabled.each do |contest|
269 contests.enabled.each do |contest|
266 contest.problems.available.each do |problem|
270 contest.problems.available.each do |problem|
267 if not pin.has_key? problem.id
271 if not pin.has_key? problem.id
268 contest_problems << problem
272 contest_problems << problem
269 end
273 end
270 pin[problem.id] = true
274 pin[problem.id] = true
271 end
275 end
272 end
276 end
273 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
277 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
274 return contest_problems + other_avaiable_problems
278 return contest_problems + other_avaiable_problems
275 end
279 end
276 end
280 end
277
281
278 # new feature, get list of available problem in all enabled group that the user belongs to
282 # new feature, get list of available problem in all enabled group that the user belongs to
279 def available_problems_in_group
283 def available_problems_in_group
280 problem = []
284 problem = []
281 self.groups.where(enabled: true).each do |group|
285 self.groups.where(enabled: true).each do |group|
282 group.problems.where(available: true).each { |p| problem << p }
286 group.problems.where(available: true).each { |p| problem << p }
283 end
287 end
284 problem.uniq!
288 problem.uniq!
285 if problem
289 if problem
286 problem.sort! do |a,b|
290 problem.sort! do |a,b|
287 case
291 case
288 when a.date_added < b.date_added
292 when a.date_added < b.date_added
289 1
293 1
290 when a.date_added > b.date_added
294 when a.date_added > b.date_added
291 -1
295 -1
292 else
296 else
293 a.name <=> b.name
297 a.name <=> b.name
294 end
298 end
295 end
299 end
296 return problem
300 return problem
297 else
301 else
298 return []
302 return []
299 end
303 end
300 end
304 end
301
305
302 #check if the user has the right to view that problem
306 #check if the user has the right to view that problem
303 #this also consider group based problem policy
307 #this also consider group based problem policy
304 def can_view_problem?(problem)
308 def can_view_problem?(problem)
305 return true if admin?
309 return true if admin?
306 return available_problems.include? problem
310 return available_problems.include? problem
307 end
311 end
308
312
309 def self.clear_last_login
313 def self.clear_last_login
310 User.update_all(:last_ip => nil)
314 User.update_all(:last_ip => nil)
311 end
315 end
312
316
313 #create multiple user, one per lines of input
317 #create multiple user, one per lines of input
314 def self.create_from_list(lines)
318 def self.create_from_list(lines)
315 error_logins = []
319 error_logins = []
316 first_error = nil
320 first_error = nil
317 created_users = []
321 created_users = []
318
322
319 lines.split("\n").each do |line|
323 lines.split("\n").each do |line|
320 #split with large limit, this will cause consecutive ',' to be result in a blank
324 #split with large limit, this will cause consecutive ',' to be result in a blank
321 items = line.chomp.split(',',1000)
325 items = line.chomp.split(',',1000)
322 if items.length>=2
326 if items.length>=2
323 login = items[0]
327 login = items[0]
324 full_name = items[1]
328 full_name = items[1]
325 remark =''
329 remark =''
326 user_alias = ''
330 user_alias = ''
327
331
328 added_random_password = false
332 added_random_password = false
329 added_password = false
333 added_password = false
330
334
331 #given password?
335 #given password?
332 if items.length >= 3
336 if items.length >= 3
333 if items[2].chomp(" ").length > 0
337 if items[2].chomp(" ").length > 0
334 password = items[2].chomp(" ")
338 password = items[2].chomp(" ")
335 added_password = true
339 added_password = true
336 end
340 end
337 else
341 else
338 password = random_password
342 password = random_password
339 added_random_password=true;
343 added_random_password=true;
340 end
344 end
341
345
342 #given alias?
346 #given alias?
343 if items.length>= 4 and items[3].chomp(" ").length > 0;
347 if items.length>= 4 and items[3].chomp(" ").length > 0;
344 user_alias = items[3].chomp(" ")
348 user_alias = items[3].chomp(" ")
345 else
349 else
346 user_alias = login
350 user_alias = login
347 end
351 end
348
352
349 #given remark?
353 #given remark?
350 has_remark = false
354 has_remark = false
351 if items.length>=5
355 if items.length>=5
352 remark = items[4].strip;
356 remark = items[4].strip;
353 has_remark = true
357 has_remark = true
354 end
358 end
355
359
356 user = User.find_by_login(login)
360 user = User.find_by_login(login)
357 if (user)
361 if (user)
358 user.full_name = full_name
362 user.full_name = full_name
359 user.remark = remark if has_remark
363 user.remark = remark if has_remark
360 user.password = password if added_password || added_random_password
364 user.password = password if added_password || added_random_password
361 else
365 else
362 #create a random password if none are given
366 #create a random password if none are given
363 password = random_password unless password
367 password = random_password unless password
364 user = User.new({:login => login,
368 user = User.new({:login => login,
365 :full_name => full_name,
369 :full_name => full_name,
366 :password => password,
370 :password => password,
367 :password_confirmation => password,
371 :password_confirmation => password,
368 :alias => user_alias,
372 :alias => user_alias,
369 :remark => remark})
373 :remark => remark})
370 end
374 end
371 user.activated = true
375 user.activated = true
372
376
373 if user.save
377 if user.save
374 created_users << user
378 created_users << user
375 else
379 else
376 error_logins << "'#{login}'"
380 error_logins << "'#{login}'"
377 first_error = user.errors.full_messages.to_sentence unless first_error
381 first_error = user.errors.full_messages.to_sentence unless first_error
378 end
382 end
379 end
383 end
380 end
384 end
381
385
382 return {error_logins: error_logins, first_error: first_error, created_users: created_users}
386 return {error_logins: error_logins, first_error: first_error, created_users: created_users}
383
387
384 end
388 end
385
389
386 def self.find_non_admin_with_prefix(prefix='')
390 def self.find_non_admin_with_prefix(prefix='')
387 users = User.all
391 users = User.all
388 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
392 return users.find_all { |u| !(u.admin?) and u.login.index(prefix)==0 }
389 end
393 end
390
394
391 protected
395 protected
392 def encrypt_new_password
396 def encrypt_new_password
393 return if password.blank?
397 return if password.blank?
394 self.salt = (10+rand(90)).to_s
398 self.salt = (10+rand(90)).to_s
395 self.hashed_password = User.encrypt(self.password,self.salt)
399 self.hashed_password = User.encrypt(self.password,self.salt)
396 end
400 end
397
401
398 def assign_default_site
402 def assign_default_site
399 # have to catch error when migrating (because self.site is not available).
403 # have to catch error when migrating (because self.site is not available).
400 begin
404 begin
401 if self.site==nil
405 if self.site==nil
402 self.site = Site.find_by_name('default')
406 self.site = Site.find_by_name('default')
403 if self.site==nil
407 if self.site==nil
404 self.site = Site.find(1) # when 'default has be renamed'
408 self.site = Site.find(1) # when 'default has be renamed'
405 end
409 end
406 end
410 end
407 rescue
411 rescue
408 end
412 end
409 end
413 end
410
414
411 def assign_default_contest
415 def assign_default_contest
412 # have to catch error when migrating (because self.site is not available).
416 # have to catch error when migrating (because self.site is not available).
413 begin
417 begin
414 if self.contests.length == 0
418 if self.contests.length == 0
415 default_contest = Contest.find_by_name(GraderConfiguration['contest.default_contest_name'])
419 default_contest = Contest.find_by_name(GraderConfiguration['contest.default_contest_name'])
416 if default_contest
420 if default_contest
417 self.contests = [default_contest]
421 self.contests = [default_contest]
418 end
422 end
419 end
423 end
420 rescue
424 rescue
421 end
425 end
422 end
426 end
423
427
424 def password_required?
428 def password_required?
425 self.hashed_password.blank? || !self.password.blank?
429 self.hashed_password.blank? || !self.password.blank?
426 end
430 end
427
431
428 def self.encrypt(string,salt)
432 def self.encrypt(string,salt)
429 Digest::SHA1.hexdigest(salt + string)
433 Digest::SHA1.hexdigest(salt + string)
430 end
434 end
431
435
432 def uniqueness_of_email_from_activated_users
436 def uniqueness_of_email_from_activated_users
433 user = User.activated_users.find_by_email(self.email)
437 user = User.activated_users.find_by_email(self.email)
434 if user and (user.login != self.login)
438 if user and (user.login != self.login)
435 self.errors.add(:base,"Email has already been taken")
439 self.errors.add(:base,"Email has already been taken")
436 end
440 end
437 end
441 end
438
442
439 def enough_time_interval_between_same_email_registrations
443 def enough_time_interval_between_same_email_registrations
440 return if !self.new_record?
444 return if !self.new_record?
441 return if self.activated
445 return if self.activated
442 open_user = User.find_by_email(self.email,
446 open_user = User.find_by_email(self.email,
443 :order => 'created_at DESC')
447 :order => 'created_at DESC')
444 if open_user and open_user.created_at and
448 if open_user and open_user.created_at and
445 (open_user.created_at > Time.now.gmtime - 5.minutes)
449 (open_user.created_at > Time.now.gmtime - 5.minutes)
446 self.errors.add(:base,"There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
450 self.errors.add(:base,"There are already unactivated registrations with this e-mail address (please wait for 5 minutes)")
447 end
451 end
448 end
452 end
449
453
450 def email_validation?
454 def email_validation?
451 begin
455 begin
452 return VALIDATE_USER_EMAILS
456 return VALIDATE_USER_EMAILS
453 rescue
457 rescue
454 return false
458 return false
455 end
459 end
456 end
460 end
457 end
461 end
@@ -1,82 +1,82
1 .container-fluid
1 .container-fluid
2 .row
2 .row
3 .col-md-6
3 .col-md-6
4 %h1 Group #{@group.name}
4 %h1 Group #{@group.name}
5 .row
5 .row
6 .col-md-6
6 .col-md-6
7 %b Description:
7 %b Description:
8 = @group.description
8 = @group.description
9 %br
9 %br
10 = link_to 'Edit', edit_group_path(@group), class: 'btn btn-primary'
10 = link_to 'Edit', edit_group_path(@group), class: 'btn btn-primary'
11 .row
11 .row
12 .col-md-12
12 .col-md-12
13 %h1 Group details
13 %h1 Group details
14 .row
14 .row
15 .col-md-6
15 .col-md-6
16 .panel.panel-default
16 .panel.panel-default
17 .panel-heading
17 .panel-heading
18 .panel-title Users in this group
18 .panel-title Users in this group
19 .panel-body
19 .panel-body
20 %ul
20 %ul
21 %li
21 %li
22 If you want to add several users to a group, it may be easier to just re-import those users in
22 If you want to add several users to a group, it may be easier to just re-import those users in
23 = link_to 'New list of users', new_list_user_admin_index_path
23 = link_to 'New list of users', new_list_user_admin_index_path
24 page. You can also use
24 page. You can also use
25 = link_to 'Bulk Manage User', bulk_manage_user_admin_index_path
25 = link_to 'Bulk Manage User', bulk_manage_user_admin_index_path
26 page.
26 page.
27 =form_tag add_user_group_path(@group), class: 'form-inline' do
27 =form_tag add_user_group_path(@group), class: 'form-inline' do
28 .form-group
28 .form-group
29 =label_tag :user_id, "User"
29 =label_tag :user_id, "User"
30 - =select_tag :user_id, options_from_collection_for_select(User.all,'id','full_name'), class: 'select2', style: 'width: 10em';
30 + =select_tag :user_id, options_from_collection_for_select(User.all,'id','login_with_name'), class: 'select2', style: 'width: 25em';
31 =submit_tag "Add",class: 'btn btn-primary'
31 =submit_tag "Add",class: 'btn btn-primary'
32
32
33
33
34 %table.table.table-hover
34 %table.table.table-hover
35 %thead
35 %thead
36 %tr
36 %tr
37 %th Login
37 %th Login
38 %th Full name
38 %th Full name
39 %th Remark
39 %th Remark
40 %th= link_to 'Remove All', remove_all_user_group_path(@group), method: :delete, :data => { :confirm => "Remove ALL USERS from group?" }, class: 'btn btn-danger btn-sm'
40 %th= link_to 'Remove All', remove_all_user_group_path(@group), method: :delete, :data => { :confirm => "Remove ALL USERS from group?" }, class: 'btn btn-danger btn-sm'
41
41
42 %tbody
42 %tbody
43 - @group.users.each do |user|
43 - @group.users.each do |user|
44 %tr
44 %tr
45 %td= user.login
45 %td= user.login
46 %td= user.full_name
46 %td= user.full_name
47 %td= user.remark
47 %td= user.remark
48 %td= link_to 'Remove', remove_user_group_path(@group,user), :method => :delete, :data => { :confirm => "Remove #{user.full_name}?" }, class: 'btn btn-danger btn-sm'
48 %td= link_to 'Remove', remove_user_group_path(@group,user), :method => :delete, :data => { :confirm => "Remove #{user.full_name}?" }, class: 'btn btn-danger btn-sm'
49 .col-md-6
49 .col-md-6
50 .panel.panel-default
50 .panel.panel-default
51 .panel-heading
51 .panel-heading
52 .panel-title Problems
52 .panel-title Problems
53 .panel-body
53 .panel-body
54 %ul
54 %ul
55 %li
55 %li
56 If you want to add several problem to a group, it may be easier to bulk manage them in the
56 If you want to add several problem to a group, it may be easier to bulk manage them in the
57 = link_to 'Bulk Manage Problems', manage_problems_path
57 = link_to 'Bulk Manage Problems', manage_problems_path
58 page
58 page
59 =form_tag add_problem_group_path(@group), class: 'form-inline' do
59 =form_tag add_problem_group_path(@group), class: 'form-inline' do
60 .form-group
60 .form-group
61 =label_tag :problem_id, "Problem"
61 =label_tag :problem_id, "Problem"
62 - =select_tag :problem_id, options_from_collection_for_select(Problem.all,'id','full_name'), class: 'select2', style: 'width: 10em';
62 + =select_tag :problem_id, options_from_collection_for_select(Problem.all,'id','long_name'), class: 'select2', style: 'width: 25em';
63 =submit_tag "Add",class: 'btn btn-primary'
63 =submit_tag "Add",class: 'btn btn-primary'
64
64
65
65
66 %table.table.table-hover
66 %table.table.table-hover
67 %thead
67 %thead
68 %tr
68 %tr
69 %th name
69 %th name
70 %th Full name
70 %th Full name
71 %th Full score
71 %th Full score
72 %th= link_to 'Remove All', remove_all_problem_group_path(@group), method: :delete, :data => { :confirm => "Remove ALL PROBLEMS from group?" }, class: 'btn btn-danger btn-sm'
72 %th= link_to 'Remove All', remove_all_problem_group_path(@group), method: :delete, :data => { :confirm => "Remove ALL PROBLEMS from group?" }, class: 'btn btn-danger btn-sm'
73
73
74 %tbody
74 %tbody
75 - @group.problems.each do |problem|
75 - @group.problems.each do |problem|
76 %tr
76 %tr
77 %td= problem.name
77 %td= problem.name
78 %td= problem.full_name
78 %td= problem.full_name
79 %td= problem.full_score
79 %td= problem.full_score
80 %td= link_to 'Remove', remove_problem_group_path(@group,problem), :method => :delete, :data => { :confirm => "Remove #{problem.full_name}?" }, class: 'btn btn-danger btn-sm'
80 %td= link_to 'Remove', remove_problem_group_path(@group,problem), :method => :delete, :data => { :confirm => "Remove #{problem.full_name}?" }, class: 'btn btn-danger btn-sm'
81
81
82
82
You need to be logged in to leave comments. Login now