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 1 class Group < ActiveRecord::Base
2 2 has_many :groups_problems, class_name: 'GroupProblem'
3 3 has_many :problems, :through => :groups_problems
4 4
5 5 has_many :groups_users, class_name: 'GroupUser'
6 6 has_many :users, :through => :groups_users
7 7
8 8 #has_and_belongs_to_many :problems
9 9 #has_and_belongs_to_many :users
10 10
11 11 def add_users_skip_existing(users_list)
12 12 new_list = []
13 - users_list.each do |u|
13 + users_list.uniq.each do |u|
14 14 new_list << u unless users.include? u
15 15 end
16 16 users << new_list
17 17 end
18 18
19 19 end
20 20
@@ -1,276 +1,280
1 1 require 'digest/sha1'
2 2 require 'net/pop'
3 3 require 'net/https'
4 4 require 'net/http'
5 5 require 'json'
6 6
7 7 class User < ActiveRecord::Base
8 8
9 9 has_and_belongs_to_many :roles
10 10
11 11 #has_and_belongs_to_many :groups
12 12 has_many :groups_users, class_name: 'GroupUser'
13 13 has_many :groups, :through => :groups_users
14 14
15 15 has_many :test_requests, -> {order(submitted_at: :desc)}
16 16
17 17 has_many :messages, -> { order(created_at: :desc) },
18 18 :class_name => "Message",
19 19 :foreign_key => "sender_id"
20 20
21 21 has_many :replied_messages, -> { order(created_at: :desc) },
22 22 :class_name => "Message",
23 23 :foreign_key => "receiver_id"
24 24
25 25 has_many :logins
26 26
27 27 has_one :contest_stat, :class_name => "UserContestStat", :dependent => :destroy
28 28
29 29 belongs_to :site
30 30 belongs_to :country
31 31
32 32 has_and_belongs_to_many :contests, -> { order(:name)}
33 33
34 34 scope :activated_users, -> {where activated: true}
35 35
36 36 validates_presence_of :login
37 37 validates_uniqueness_of :login
38 38 validates_format_of :login, :with => /\A[\_A-Za-z0-9]+\z/
39 39 validates_length_of :login, :within => 3..30
40 40
41 41 validates_presence_of :full_name
42 42 validates_length_of :full_name, :minimum => 1
43 43
44 44 validates_presence_of :password, :if => :password_required?
45 45 validates_length_of :password, :within => 4..50, :if => :password_required?
46 46 validates_confirmation_of :password, :if => :password_required?
47 47
48 48 validates_format_of :email,
49 49 :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i,
50 50 :if => :email_validation?
51 51 validate :uniqueness_of_email_from_activated_users,
52 52 :if => :email_validation?
53 53 validate :enough_time_interval_between_same_email_registrations,
54 54 :if => :email_validation?
55 55
56 56 # these are for ytopc
57 57 # disable for now
58 58 #validates_presence_of :province
59 59
60 60 attr_accessor :password
61 61
62 62 before_save :encrypt_new_password
63 63 before_save :assign_default_site
64 64 before_save :assign_default_contest
65 65
66 66 # this is for will_paginate
67 67 cattr_reader :per_page
68 68 @@per_page = 50
69 69
70 70 def self.authenticate(login, password)
71 71 user = find_by_login(login)
72 72 if user
73 73 return user if user.authenticated?(password)
74 74 end
75 75 end
76 76
77 77 def authenticated?(password)
78 78 if self.activated
79 79 hashed_password == User.encrypt(password,self.salt)
80 80 else
81 81 false
82 82 end
83 83 end
84 84
85 + def login_with_name
86 + "[#{login}] #{full_name}"
87 + end
88 +
85 89 def admin?
86 90 has_role?('admin')
87 91 end
88 92
89 93 def has_role?(role)
90 94 self.roles.where(name: role).count > 0
91 95 end
92 96
93 97 def email_for_editing
94 98 if self.email==nil
95 99 "(unknown)"
96 100 elsif self.email==''
97 101 "(blank)"
98 102 else
99 103 self.email
100 104 end
101 105 end
102 106
103 107 def email_for_editing=(e)
104 108 self.email=e
105 109 end
106 110
107 111 def alias_for_editing
108 112 if self.alias==nil
109 113 "(unknown)"
110 114 elsif self.alias==''
111 115 "(blank)"
112 116 else
113 117 self.alias
114 118 end
115 119 end
116 120
117 121 def alias_for_editing=(e)
118 122 self.alias=e
119 123 end
120 124
121 125 def activation_key
122 126 if self.hashed_password==nil
123 127 encrypt_new_password
124 128 end
125 129 Digest::SHA1.hexdigest(self.hashed_password)[0..7]
126 130 end
127 131
128 132 def verify_activation_key(key)
129 133 key == activation_key
130 134 end
131 135
132 136 def self.random_password(length=5)
133 137 chars = 'abcdefghjkmnopqrstuvwxyz'
134 138 password = ''
135 139 length.times { password << chars[rand(chars.length - 1)] }
136 140 password
137 141 end
138 142
139 143
140 144 # Contest information
141 145
142 146 def self.find_users_with_no_contest()
143 147 users = User.all
144 148 return users.find_all { |u| u.contests.length == 0 }
145 149 end
146 150
147 151
148 152 def contest_time_left
149 153 if GraderConfiguration.contest_mode?
150 154 return nil if site==nil
151 155 return site.time_left
152 156 elsif GraderConfiguration.indv_contest_mode?
153 157 time_limit = GraderConfiguration.contest_time_limit
154 158 if time_limit == nil
155 159 return nil
156 160 end
157 161 if contest_stat==nil or contest_stat.started_at==nil
158 162 return (Time.now.gmtime + time_limit) - Time.now.gmtime
159 163 else
160 164 finish_time = contest_stat.started_at + time_limit
161 165 current_time = Time.now.gmtime
162 166 if current_time > finish_time
163 167 return 0
164 168 else
165 169 return finish_time - current_time
166 170 end
167 171 end
168 172 else
169 173 return nil
170 174 end
171 175 end
172 176
173 177 def contest_finished?
174 178 if GraderConfiguration.contest_mode?
175 179 return false if site==nil
176 180 return site.finished?
177 181 elsif GraderConfiguration.indv_contest_mode?
178 182 return false if self.contest_stat==nil
179 183 return contest_time_left == 0
180 184 else
181 185 return false
182 186 end
183 187 end
184 188
185 189 def contest_started?
186 190 if GraderConfiguration.indv_contest_mode?
187 191 stat = self.contest_stat
188 192 return ((stat != nil) and (stat.started_at != nil))
189 193 elsif GraderConfiguration.contest_mode?
190 194 return true if site==nil
191 195 return site.started
192 196 else
193 197 return true
194 198 end
195 199 end
196 200
197 201 def update_start_time
198 202 stat = self.contest_stat
199 203 if stat.nil? or stat.started_at.nil?
200 204 stat ||= UserContestStat.new(:user => self)
201 205 stat.started_at = Time.now.gmtime
202 206 stat.save
203 207 end
204 208 end
205 209
206 210 def problem_in_user_contests?(problem)
207 211 problem_contests = problem.contests.all
208 212
209 213 if problem_contests.length == 0 # this is public contest
210 214 return true
211 215 end
212 216
213 217 contests.each do |contest|
214 218 if problem_contests.find {|c| c.id == contest.id }
215 219 return true
216 220 end
217 221 end
218 222 return false
219 223 end
220 224
221 225 def available_problems_group_by_contests
222 226 contest_problems = []
223 227 pin = {}
224 228 contests.enabled.each do |contest|
225 229 available_problems = contest.problems.available
226 230 contest_problems << {
227 231 :contest => contest,
228 232 :problems => available_problems
229 233 }
230 234 available_problems.each {|p| pin[p.id] = true}
231 235 end
232 236 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
233 237 contest_problems << {
234 238 :contest => nil,
235 239 :problems => other_avaiable_problems
236 240 }
237 241 return contest_problems
238 242 end
239 243
240 244 def solve_all_available_problems?
241 245 available_problems.each do |p|
242 246 u = self
243 247 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
244 248 return false if !p or !sub or sub.points < p.full_score
245 249 end
246 250 return true
247 251 end
248 252
249 253 #get a list of available problem
250 254 def available_problems
251 255 # first, we check if this is normal mode
252 256 if not GraderConfiguration.multicontests?
253 257
254 258 #if this is a normal mode
255 259 #we show problem based on problem_group, if the config said so
256 260 if GraderConfiguration.use_problem_group?
257 261 return available_problems_in_group
258 262 else
259 263 return Problem.available_problems
260 264 end
261 265 else
262 266 #this is multi contest mode
263 267 contest_problems = []
264 268 pin = {}
265 269 contests.enabled.each do |contest|
266 270 contest.problems.available.each do |problem|
267 271 if not pin.has_key? problem.id
268 272 contest_problems << problem
269 273 end
270 274 pin[problem.id] = true
271 275 end
272 276 end
273 277 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
274 278 return contest_problems + other_avaiable_problems
275 279 end
276 280 end
@@ -1,82 +1,82
1 1 .container-fluid
2 2 .row
3 3 .col-md-6
4 4 %h1 Group #{@group.name}
5 5 .row
6 6 .col-md-6
7 7 %b Description:
8 8 = @group.description
9 9 %br
10 10 = link_to 'Edit', edit_group_path(@group), class: 'btn btn-primary'
11 11 .row
12 12 .col-md-12
13 13 %h1 Group details
14 14 .row
15 15 .col-md-6
16 16 .panel.panel-default
17 17 .panel-heading
18 18 .panel-title Users in this group
19 19 .panel-body
20 20 %ul
21 21 %li
22 22 If you want to add several users to a group, it may be easier to just re-import those users in
23 23 = link_to 'New list of users', new_list_user_admin_index_path
24 24 page. You can also use
25 25 = link_to 'Bulk Manage User', bulk_manage_user_admin_index_path
26 26 page.
27 27 =form_tag add_user_group_path(@group), class: 'form-inline' do
28 28 .form-group
29 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 31 =submit_tag "Add",class: 'btn btn-primary'
32 32
33 33
34 34 %table.table.table-hover
35 35 %thead
36 36 %tr
37 37 %th Login
38 38 %th Full name
39 39 %th Remark
40 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 42 %tbody
43 43 - @group.users.each do |user|
44 44 %tr
45 45 %td= user.login
46 46 %td= user.full_name
47 47 %td= user.remark
48 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 49 .col-md-6
50 50 .panel.panel-default
51 51 .panel-heading
52 52 .panel-title Problems
53 53 .panel-body
54 54 %ul
55 55 %li
56 56 If you want to add several problem to a group, it may be easier to bulk manage them in the
57 57 = link_to 'Bulk Manage Problems', manage_problems_path
58 58 page
59 59 =form_tag add_problem_group_path(@group), class: 'form-inline' do
60 60 .form-group
61 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 63 =submit_tag "Add",class: 'btn btn-primary'
64 64
65 65
66 66 %table.table.table-hover
67 67 %thead
68 68 %tr
69 69 %th name
70 70 %th Full name
71 71 %th Full score
72 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 74 %tbody
75 75 - @group.problems.each do |problem|
76 76 %tr
77 77 %td= problem.name
78 78 %td= problem.full_name
79 79 %td= problem.full_score
80 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