Description:
better user import
Commit status:
[Not Reviewed]
References:
Diff options:
Comments:
0 Commit comments
0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
r798:46ce575fc051 - - 6 files changed: 29 inserted, 18 deleted
@@ -1,482 +1,492 | |||
|
1 | 1 | require 'csv' |
|
2 | 2 | |
|
3 | 3 | class UserAdminController < ApplicationController |
|
4 | 4 | |
|
5 | 5 | include MailHelperMethods |
|
6 | 6 | |
|
7 | 7 | before_action :admin_authorization |
|
8 | 8 | |
|
9 | 9 | def index |
|
10 | 10 | @user_count = User.count |
|
11 | 11 | if params[:page] == 'all' |
|
12 | 12 | @users = User.all |
|
13 | 13 | @paginated = false |
|
14 | 14 | else |
|
15 | 15 | @users = User.paginate :page => params[:page] |
|
16 | 16 | @paginated = true |
|
17 | 17 | end |
|
18 | 18 | @users = User.all |
|
19 | 19 | @hidden_columns = ['hashed_password', 'salt', 'created_at', 'updated_at'] |
|
20 | 20 | @contests = Contest.enabled |
|
21 | 21 | end |
|
22 | 22 | |
|
23 | 23 | def active |
|
24 | 24 | sessions = ActiveRecord::SessionStore::Session.where("updated_at >= ?", 60.minutes.ago) |
|
25 | 25 | @users = [] |
|
26 | 26 | sessions.each do |session| |
|
27 | 27 | if session.data[:user_id] |
|
28 | 28 | @users << User.find(session.data[:user_id]) |
|
29 | 29 | end |
|
30 | 30 | end |
|
31 | 31 | end |
|
32 | 32 | |
|
33 | 33 | def show |
|
34 | 34 | @user = User.find(params[:id]) |
|
35 | 35 | end |
|
36 | 36 | |
|
37 | 37 | def new |
|
38 | 38 | @user = User.new |
|
39 | 39 | end |
|
40 | 40 | |
|
41 | 41 | def create |
|
42 | 42 | @user = User.new(user_params) |
|
43 | 43 | @user.activated = true |
|
44 | 44 | if @user.save |
|
45 | 45 | flash[:notice] = 'User was successfully created.' |
|
46 | 46 | redirect_to :action => 'index' |
|
47 | 47 | else |
|
48 | 48 | render :action => 'new' |
|
49 | 49 | end |
|
50 | 50 | end |
|
51 | 51 | |
|
52 | 52 | def clear_last_ip |
|
53 | 53 | @user = User.find(params[:id]) |
|
54 | 54 | @user.last_ip = nil |
|
55 | 55 | @user.save |
|
56 | 56 | redirect_to action: 'index', page: params[:page] |
|
57 | 57 | end |
|
58 | 58 | |
|
59 | 59 | def create_from_list |
|
60 | 60 | lines = params[:user_list] |
|
61 | 61 | |
|
62 | 62 | note = [] |
|
63 | 63 | error_note = [] |
|
64 | 64 | error_msg = nil |
|
65 | 65 | ok_user = [] |
|
66 | 66 | |
|
67 | 67 | lines.split("\n").each do |line| |
|
68 | - items = line.chomp.split(',') | |
|
68 | + #split with large limit, this will cause consecutive ',' to be result in a blank | |
|
69 | + items = line.chomp.split(',',1000) | |
|
69 | 70 | if items.length>=2 |
|
70 | 71 | login = items[0] |
|
71 | 72 | full_name = items[1] |
|
72 | 73 | remark ='' |
|
73 | 74 | user_alias = '' |
|
74 | 75 | |
|
75 | 76 | added_random_password = false |
|
76 | - if items.length >= 3 and items[2].chomp(" ").length > 0; | |
|
77 | - password = items[2].chomp(" ") | |
|
77 | + added_password = false | |
|
78 | + if items.length >= 3 | |
|
79 | + if items[2].chomp(" ").length > 0 | |
|
80 | + password = items[2].chomp(" ") | |
|
81 | + added_password = true | |
|
82 | + end | |
|
78 | 83 | else |
|
79 | 84 | password = random_password |
|
80 | 85 | added_random_password=true; |
|
81 | 86 | end |
|
82 | 87 | |
|
83 | 88 | if items.length>= 4 and items[3].chomp(" ").length > 0; |
|
84 | 89 | user_alias = items[3].chomp(" ") |
|
85 | 90 | else |
|
86 | 91 | user_alias = login |
|
87 | 92 | end |
|
88 | 93 | |
|
94 | + | |
|
95 | + has_remark = false | |
|
89 | 96 | if items.length>=5 |
|
90 | 97 | remark = items[4].strip; |
|
98 | + has_remark = true | |
|
91 | 99 | end |
|
92 | 100 | |
|
93 | 101 | user = User.find_by_login(login) |
|
94 | 102 | if (user) |
|
95 | 103 | user.full_name = full_name |
|
96 | - user.password = password | |
|
97 | - user.remark = remark | |
|
104 | + user.remark = remark if has_remark | |
|
105 | + user.password = password if added_password || added_random_password | |
|
98 | 106 | else |
|
107 | + #create a random password if none are given | |
|
108 | + password = random_password unless password | |
|
99 | 109 | user = User.new({:login => login, |
|
100 | 110 | :full_name => full_name, |
|
101 | 111 | :password => password, |
|
102 | 112 | :password_confirmation => password, |
|
103 | 113 | :alias => user_alias, |
|
104 | 114 | :remark => remark}) |
|
105 | 115 | end |
|
106 | 116 | user.activated = true |
|
107 | 117 | |
|
108 | 118 | if user.save |
|
109 | 119 | if added_random_password |
|
110 | 120 | note << "'#{login}' (+)" |
|
111 | 121 | else |
|
112 | 122 | note << login |
|
113 | 123 | end |
|
114 | 124 | ok_user << user |
|
115 | 125 | else |
|
116 | 126 | error_note << "'#{login}'" |
|
117 | 127 | error_msg = user.errors.full_messages.to_sentence unless error_msg |
|
118 | 128 | end |
|
119 | 129 | |
|
120 | 130 | end |
|
121 | 131 | end |
|
122 | 132 | |
|
123 | 133 | #add to group |
|
124 | 134 | if params[:add_to_group] |
|
125 | 135 | group = Group.where(id: params[:group_id]).first |
|
126 | 136 | if group |
|
127 | 137 | group.users << ok_user |
|
128 | 138 | end |
|
129 | 139 | end |
|
130 | 140 | |
|
131 | 141 | # show flash |
|
132 | 142 | if note.size > 0 |
|
133 | 143 | flash[:success] = 'User(s) ' + note.join(', ') + |
|
134 | 144 | ' were successfully created. ' + |
|
135 | 145 | '( (+) - created with random passwords.)' |
|
136 | 146 | end |
|
137 | 147 | if error_note.size > 0 |
|
138 | 148 | flash[:error] = "Following user(s) failed to be created: " + error_note.join(', ') + ". The error of the first failed one are: " + error_msg; |
|
139 | 149 | end |
|
140 | 150 | redirect_to :action => 'index' |
|
141 | 151 | end |
|
142 | 152 | |
|
143 | 153 | def edit |
|
144 | 154 | @user = User.find(params[:id]) |
|
145 | 155 | end |
|
146 | 156 | |
|
147 | 157 | def update |
|
148 | 158 | @user = User.find(params[:id]) |
|
149 | 159 | if @user.update_attributes(user_params) |
|
150 | 160 | flash[:notice] = 'User was successfully updated.' |
|
151 | 161 | redirect_to :action => 'show', :id => @user |
|
152 | 162 | else |
|
153 | 163 | render :action => 'edit' |
|
154 | 164 | end |
|
155 | 165 | end |
|
156 | 166 | |
|
157 | 167 | def destroy |
|
158 | 168 | User.find(params[:id]).destroy |
|
159 | 169 | redirect_to :action => 'index' |
|
160 | 170 | end |
|
161 | 171 | |
|
162 | 172 | def user_stat |
|
163 | 173 | if params[:commit] == 'download csv' |
|
164 | 174 | @problems = Problem.all |
|
165 | 175 | else |
|
166 | 176 | @problems = Problem.available_problems |
|
167 | 177 | end |
|
168 | 178 | @users = User.includes(:contests, :contest_stat).where(enabled: true) |
|
169 | 179 | @scorearray = Array.new |
|
170 | 180 | @users.each do |u| |
|
171 | 181 | ustat = Array.new |
|
172 | 182 | ustat[0] = u |
|
173 | 183 | @problems.each do |p| |
|
174 | 184 | sub = Submission.find_last_by_user_and_problem(u.id,p.id) |
|
175 | 185 | if (sub!=nil) and (sub.points!=nil) and p and p.full_score |
|
176 | 186 | ustat << [(sub.points.to_f*100/p.full_score).round, (sub.points>=p.full_score)] |
|
177 | 187 | else |
|
178 | 188 | ustat << [0,false] |
|
179 | 189 | end |
|
180 | 190 | end |
|
181 | 191 | @scorearray << ustat |
|
182 | 192 | end |
|
183 | 193 | if params[:commit] == 'download csv' then |
|
184 | 194 | csv = gen_csv_from_scorearray(@scorearray,@problems) |
|
185 | 195 | send_data csv, filename: 'last_score.csv' |
|
186 | 196 | else |
|
187 | 197 | render template: 'user_admin/user_stat' |
|
188 | 198 | end |
|
189 | 199 | end |
|
190 | 200 | |
|
191 | 201 | def user_stat_max |
|
192 | 202 | if params[:commit] == 'download csv' |
|
193 | 203 | @problems = Problem.all |
|
194 | 204 | else |
|
195 | 205 | @problems = Problem.available_problems |
|
196 | 206 | end |
|
197 | 207 | @users = User.includes(:contests).includes(:contest_stat).all |
|
198 | 208 | @scorearray = Array.new |
|
199 | 209 | #set up range from param |
|
200 | 210 | since_id = params.fetch(:since_id, 0).to_i |
|
201 | 211 | until_id = params.fetch(:until_id, 0).to_i |
|
202 | 212 | @users.each do |u| |
|
203 | 213 | ustat = Array.new |
|
204 | 214 | ustat[0] = u |
|
205 | 215 | @problems.each do |p| |
|
206 | 216 | max_points = 0 |
|
207 | 217 | Submission.find_in_range_by_user_and_problem(u.id,p.id,since_id,until_id).each do |sub| |
|
208 | 218 | max_points = sub.points if sub and sub.points and (sub.points > max_points) |
|
209 | 219 | end |
|
210 | 220 | ustat << [(max_points.to_f*100/p.full_score).round, (max_points>=p.full_score)] |
|
211 | 221 | end |
|
212 | 222 | @scorearray << ustat |
|
213 | 223 | end |
|
214 | 224 | |
|
215 | 225 | if params[:commit] == 'download csv' then |
|
216 | 226 | csv = gen_csv_from_scorearray(@scorearray,@problems) |
|
217 | 227 | send_data csv, filename: 'max_score.csv' |
|
218 | 228 | else |
|
219 | 229 | render template: 'user_admin/user_stat' |
|
220 | 230 | end |
|
221 | 231 | end |
|
222 | 232 | |
|
223 | 233 | def import |
|
224 | 234 | if params[:file]=='' |
|
225 | 235 | flash[:notice] = 'Error importing no file' |
|
226 | 236 | redirect_to :action => 'index' and return |
|
227 | 237 | end |
|
228 | 238 | import_from_file(params[:file]) |
|
229 | 239 | end |
|
230 | 240 | |
|
231 | 241 | def random_all_passwords |
|
232 | 242 | users = User.all |
|
233 | 243 | @prefix = params[:prefix] || '' |
|
234 | 244 | @non_admin_users = User.find_non_admin_with_prefix(@prefix) |
|
235 | 245 | @changed = false |
|
236 | 246 | if params[:commit] == 'Go ahead' |
|
237 | 247 | @non_admin_users.each do |user| |
|
238 | 248 | password = random_password |
|
239 | 249 | user.password = password |
|
240 | 250 | user.password_confirmation = password |
|
241 | 251 | user.save |
|
242 | 252 | end |
|
243 | 253 | @changed = true |
|
244 | 254 | end |
|
245 | 255 | end |
|
246 | 256 | |
|
247 | 257 | # contest management |
|
248 | 258 | |
|
249 | 259 | def contests |
|
250 | 260 | @contest, @users = find_contest_and_user_from_contest_id(params[:id]) |
|
251 | 261 | @contests = Contest.enabled |
|
252 | 262 | end |
|
253 | 263 | |
|
254 | 264 | def assign_from_list |
|
255 | 265 | contest_id = params[:users_contest_id] |
|
256 | 266 | org_contest, users = find_contest_and_user_from_contest_id(contest_id) |
|
257 | 267 | contest = Contest.find(params[:new_contest][:id]) |
|
258 | 268 | if !contest |
|
259 | 269 | flash[:notice] = 'Error: no contest' |
|
260 | 270 | redirect_to :action => 'contests', :id =>contest_id |
|
261 | 271 | end |
|
262 | 272 | |
|
263 | 273 | note = [] |
|
264 | 274 | users.each do |u| |
|
265 | 275 | u.contests = [contest] |
|
266 | 276 | note << u.login |
|
267 | 277 | end |
|
268 | 278 | flash[:notice] = 'User(s) ' + note.join(', ') + |
|
269 | 279 | " were successfully reassigned to #{contest.title}." |
|
270 | 280 | redirect_to :action => 'contests', :id =>contest.id |
|
271 | 281 | end |
|
272 | 282 | |
|
273 | 283 | def add_to_contest |
|
274 | 284 | user = User.find(params[:id]) |
|
275 | 285 | contest = Contest.find(params[:contest_id]) |
|
276 | 286 | if user and contest |
|
277 | 287 | user.contests << contest |
|
278 | 288 | end |
|
279 | 289 | redirect_to :action => 'index' |
|
280 | 290 | end |
|
281 | 291 | |
|
282 | 292 | def remove_from_contest |
|
283 | 293 | user = User.find(params[:id]) |
|
284 | 294 | contest = Contest.find(params[:contest_id]) |
|
285 | 295 | if user and contest |
|
286 | 296 | user.contests.delete(contest) |
|
287 | 297 | end |
|
288 | 298 | redirect_to :action => 'index' |
|
289 | 299 | end |
|
290 | 300 | |
|
291 | 301 | def contest_management |
|
292 | 302 | end |
|
293 | 303 | |
|
294 | 304 | def manage_contest |
|
295 | 305 | contest = Contest.find(params[:contest][:id]) |
|
296 | 306 | if !contest |
|
297 | 307 | flash[:notice] = 'You did not choose the contest.' |
|
298 | 308 | redirect_to :action => 'contest_management' and return |
|
299 | 309 | end |
|
300 | 310 | |
|
301 | 311 | operation = params[:operation] |
|
302 | 312 | |
|
303 | 313 | if not ['add','remove','assign'].include? operation |
|
304 | 314 | flash[:notice] = 'You did not choose the operation to perform.' |
|
305 | 315 | redirect_to :action => 'contest_management' and return |
|
306 | 316 | end |
|
307 | 317 | |
|
308 | 318 | lines = params[:login_list] |
|
309 | 319 | if !lines or lines.blank? |
|
310 | 320 | flash[:notice] = 'You entered an empty list.' |
|
311 | 321 | redirect_to :action => 'contest_management' and return |
|
312 | 322 | end |
|
313 | 323 | |
|
314 | 324 | note = [] |
|
315 | 325 | users = [] |
|
316 | 326 | lines.split("\n").each do |line| |
|
317 | 327 | user = User.find_by_login(line.chomp) |
|
318 | 328 | if user |
|
319 | 329 | if operation=='add' |
|
320 | 330 | if ! user.contests.include? contest |
|
321 | 331 | user.contests << contest |
|
322 | 332 | end |
|
323 | 333 | elsif operation=='remove' |
|
324 | 334 | user.contests.delete(contest) |
|
325 | 335 | else |
|
326 | 336 | user.contests = [contest] |
|
327 | 337 | end |
|
328 | 338 | |
|
329 | 339 | if params[:reset_timer] |
|
330 | 340 | user.contest_stat.forced_logout = true |
|
331 | 341 | user.contest_stat.reset_timer_and_save |
|
332 | 342 | end |
|
333 | 343 | |
|
334 | 344 | if params[:notification_emails] |
|
335 | 345 | send_contest_update_notification_email(user, contest) |
|
336 | 346 | end |
|
337 | 347 | |
|
338 | 348 | note << user.login |
|
339 | 349 | users << user |
|
340 | 350 | end |
|
341 | 351 | end |
|
342 | 352 | |
|
343 | 353 | if params[:reset_timer] |
|
344 | 354 | logout_users(users) |
|
345 | 355 | end |
|
346 | 356 | |
|
347 | 357 | flash[:notice] = 'User(s) ' + note.join(', ') + |
|
348 | 358 | ' were successfully modified. ' |
|
349 | 359 | redirect_to :action => 'contest_management' |
|
350 | 360 | end |
|
351 | 361 | |
|
352 | 362 | # admin management |
|
353 | 363 | |
|
354 | 364 | def admin |
|
355 | 365 | @admins = User.all.find_all {|user| user.admin? } |
|
356 | 366 | end |
|
357 | 367 | |
|
358 | 368 | def grant_admin |
|
359 | 369 | login = params[:login] |
|
360 | 370 | user = User.find_by_login(login) |
|
361 | 371 | if user!=nil |
|
362 | 372 | admin_role = Role.find_by_name('admin') |
|
363 | 373 | user.roles << admin_role |
|
364 | 374 | else |
|
365 | 375 | flash[:notice] = 'Unknown user' |
|
366 | 376 | end |
|
367 | 377 | flash[:notice] = 'User added as admins' |
|
368 | 378 | redirect_to :action => 'admin' |
|
369 | 379 | end |
|
370 | 380 | |
|
371 | 381 | def revoke_admin |
|
372 | 382 | user = User.find(params[:id]) |
|
373 | 383 | if user==nil |
|
374 | 384 | flash[:notice] = 'Unknown user' |
|
375 | 385 | redirect_to :action => 'admin' and return |
|
376 | 386 | elsif user.login == 'root' |
|
377 | 387 | flash[:notice] = 'You cannot revoke admisnistrator permission from root.' |
|
378 | 388 | redirect_to :action => 'admin' and return |
|
379 | 389 | end |
|
380 | 390 | |
|
381 | 391 | admin_role = Role.find_by_name('admin') |
|
382 | 392 | user.roles.delete(admin_role) |
|
383 | 393 | flash[:notice] = 'User permission revoked' |
|
384 | 394 | redirect_to :action => 'admin' |
|
385 | 395 | end |
|
386 | 396 | |
|
387 | 397 | # mass mailing |
|
388 | 398 | |
|
389 | 399 | def mass_mailing |
|
390 | 400 | end |
|
391 | 401 | |
|
392 | 402 | def bulk_mail |
|
393 | 403 | lines = params[:login_list] |
|
394 | 404 | if !lines or lines.blank? |
|
395 | 405 | flash[:notice] = 'You entered an empty list.' |
|
396 | 406 | redirect_to :action => 'mass_mailing' and return |
|
397 | 407 | end |
|
398 | 408 | |
|
399 | 409 | mail_subject = params[:subject] |
|
400 | 410 | if !mail_subject or mail_subject.blank? |
|
401 | 411 | flash[:notice] = 'You entered an empty mail subject.' |
|
402 | 412 | redirect_to :action => 'mass_mailing' and return |
|
403 | 413 | end |
|
404 | 414 | |
|
405 | 415 | mail_body = params[:email_body] |
|
406 | 416 | if !mail_body or mail_body.blank? |
|
407 | 417 | flash[:notice] = 'You entered an empty mail body.' |
|
408 | 418 | redirect_to :action => 'mass_mailing' and return |
|
409 | 419 | end |
|
410 | 420 | |
|
411 | 421 | note = [] |
|
412 | 422 | users = [] |
|
413 | 423 | lines.split("\n").each do |line| |
|
414 | 424 | user = User.find_by_login(line.chomp) |
|
415 | 425 | if user |
|
416 | 426 | send_mail(user.email, mail_subject, mail_body) |
|
417 | 427 | note << user.login |
|
418 | 428 | end |
|
419 | 429 | end |
|
420 | 430 | |
|
421 | 431 | flash[:notice] = 'User(s) ' + note.join(', ') + |
|
422 | 432 | ' were successfully modified. ' |
|
423 | 433 | redirect_to :action => 'mass_mailing' |
|
424 | 434 | end |
|
425 | 435 | |
|
426 | 436 | #bulk manage |
|
427 | 437 | def bulk_manage |
|
428 | 438 | |
|
429 | 439 | begin |
|
430 | 440 | @users = User.where('(login REGEXP ?) OR (remark REGEXP ?)',params[:regex],params[:regex]) if params[:regex] |
|
431 | 441 | @users.count if @users #i don't know why I have to call count, but if I won't exception is not raised |
|
432 | 442 | rescue Exception |
|
433 | 443 | flash[:error] = 'Regular Expression is malformed' |
|
434 | 444 | @users = nil |
|
435 | 445 | end |
|
436 | 446 | |
|
437 | 447 | if params[:commit] |
|
438 | 448 | @action = {} |
|
439 | 449 | @action[:set_enable] = params[:enabled] |
|
440 | 450 | @action[:enabled] = params[:enable] == "1" |
|
441 | 451 | @action[:gen_password] = params[:gen_password] |
|
442 | 452 | @action[:add_group] = params[:add_group] |
|
443 | 453 | @action[:group_name] = params[:group_name] |
|
444 | 454 | end |
|
445 | 455 | |
|
446 | 456 | if params[:commit] == "Perform" |
|
447 | 457 | if @action[:set_enable] |
|
448 | 458 | @users.update_all(enabled: @action[:enabled]) |
|
449 | 459 | end |
|
450 | 460 | if @action[:gen_password] |
|
451 | 461 | @users.each do |u| |
|
452 | 462 | password = random_password |
|
453 | 463 | u.password = password |
|
454 | 464 | u.password_confirmation = password |
|
455 | 465 | u.save |
|
456 | 466 | end |
|
457 | 467 | end |
|
458 | 468 | if @action[:add_group] and @action[:group_name] |
|
459 | 469 | @group = Group.find(@action[:group_name]) |
|
460 | 470 | ok = [] |
|
461 | 471 | failed = [] |
|
462 | 472 | @users.each do |user| |
|
463 | 473 | begin |
|
464 | 474 | @group.users << user |
|
465 | 475 | ok << user.login |
|
466 | 476 | rescue => e |
|
467 | 477 | failed << user.login |
|
468 | 478 | end |
|
469 | 479 | end |
|
470 | 480 | flash[:success] = "The following users are added to the 'group #{@group.name}': " + ok.join(', ') if ok.count > 0 |
|
471 | 481 | flash[:alert] = "The following users are already in the 'group #{@group.name}': " + failed.join(', ') if failed.count > 0 |
|
472 | 482 | end |
|
473 | 483 | end |
|
474 | 484 | end |
|
475 | 485 | |
|
476 | 486 | protected |
|
477 | 487 | |
|
478 | 488 | def random_password(length=5) |
|
479 | 489 | chars = 'abcdefghijkmnopqrstuvwxyz23456789' |
|
480 | 490 | newpass = "" |
|
481 | 491 | length.times { newpass << chars[rand(chars.size-1)] } |
|
482 | 492 | return newpass |
@@ -1,225 +1,222 | |||
|
1 | 1 | # Methods added to this helper will be available to all templates in the application. |
|
2 | 2 | module ApplicationHelper |
|
3 | 3 | |
|
4 | 4 | #new bootstrap header |
|
5 | 5 | def navbar_user_header |
|
6 | 6 | left_menu = '' |
|
7 | 7 | right_menu = '' |
|
8 | 8 | user = User.find(session[:user_id]) |
|
9 | 9 | |
|
10 | 10 | if (user!=nil) and (GraderConfiguration.show_tasks_to?(user)) |
|
11 | 11 | left_menu << add_menu("#{I18n.t 'menu.tasks'}", 'tasks', 'list') |
|
12 | 12 | left_menu << add_menu("#{I18n.t 'menu.submissions'}", 'main', 'submission') |
|
13 | 13 | left_menu << add_menu("#{I18n.t 'menu.test'}", 'test', 'index') |
|
14 | 14 | end |
|
15 | 15 | |
|
16 | 16 | if GraderConfiguration['right.user_hall_of_fame'] |
|
17 | 17 | left_menu << add_menu("#{I18n.t 'menu.hall_of_fame'}", 'report', 'problem_hof') |
|
18 | 18 | end |
|
19 | 19 | |
|
20 | 20 | right_menu << add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-question-sign')}".html_safe, 'main', 'help') |
|
21 | 21 | right_menu << add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-comment')}".html_safe, 'messages', 'list', {title: I18n.t('menu.messages'), data: {toggle: 'tooltip'}}) |
|
22 | 22 | if GraderConfiguration['system.user_setting_enabled'] |
|
23 | 23 | right_menu << add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-cog')}".html_safe, 'users', 'index', {title: I18n.t('menu.settings'), data: {toggle: 'tooltip'}}) |
|
24 | 24 | end |
|
25 | 25 | right_menu << add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-log-out')} #{user.full_name}".html_safe, 'main', 'login', {title: I18n.t('menu.log_out'), data: {toggle: 'tooltip'}}) |
|
26 | 26 | |
|
27 | 27 | |
|
28 | 28 | result = content_tag(:ul,left_menu.html_safe,class: 'nav navbar-nav') + content_tag(:ul,right_menu.html_safe,class: 'nav navbar-nav navbar-right') |
|
29 | 29 | end |
|
30 | 30 | |
|
31 | 31 | def add_menu(title, controller, action, html_option = {}) |
|
32 | 32 | link_option = {controller: controller, action: action} |
|
33 | 33 | html_option[:class] = (html_option[:class] || '') + " active" if current_page?(link_option) |
|
34 | 34 | content_tag(:li, link_to(title,link_option),html_option) |
|
35 | 35 | end |
|
36 | 36 | |
|
37 | 37 | def user_header |
|
38 | 38 | menu_items = '' |
|
39 | 39 | user = User.find(session[:user_id]) |
|
40 | 40 | |
|
41 | 41 | if (user!=nil) and (session[:admin]) |
|
42 | 42 | # admin menu |
|
43 | 43 | menu_items << "<b>Administrative task:</b> " |
|
44 | 44 | append_to menu_items, '[Announcements]', 'announcements', 'index' |
|
45 | 45 | append_to menu_items, '[Msg console]', 'messages', 'console' |
|
46 | 46 | append_to menu_items, '[Problems]', 'problems', 'index' |
|
47 | 47 | append_to menu_items, '[Users]', 'user_admin', 'index' |
|
48 | 48 | append_to menu_items, '[Results]', 'user_admin', 'user_stat' |
|
49 | 49 | append_to menu_items, '[Report]', 'report', 'multiple_login' |
|
50 | 50 | append_to menu_items, '[Graders]', 'graders', 'list' |
|
51 | 51 | append_to menu_items, '[Contests]', 'contest_management', 'index' |
|
52 | 52 | append_to menu_items, '[Sites]', 'sites', 'index' |
|
53 | 53 | append_to menu_items, '[System config]', 'configurations', 'index' |
|
54 | 54 | menu_items << "<br/>" |
|
55 | 55 | end |
|
56 | 56 | |
|
57 | 57 | # main page |
|
58 | 58 | append_to menu_items, "[#{I18n.t 'menu.main'}]", 'main', 'list' |
|
59 | 59 | append_to menu_items, "[#{I18n.t 'menu.messages'}]", 'messages', 'list' |
|
60 | 60 | |
|
61 | 61 | if (user!=nil) and (GraderConfiguration.show_tasks_to?(user)) |
|
62 | 62 | append_to menu_items, "[#{I18n.t 'menu.tasks'}]", 'tasks', 'list' |
|
63 | 63 | append_to menu_items, "[#{I18n.t 'menu.submissions'}]", 'main', 'submission' |
|
64 | 64 | append_to menu_items, "[#{I18n.t 'menu.test'}]", 'test', 'index' |
|
65 | 65 | end |
|
66 | 66 | |
|
67 | 67 | if GraderConfiguration['right.user_hall_of_fame'] |
|
68 | 68 | append_to menu_items, "[#{I18n.t 'menu.hall_of_fame'}]", 'report', 'problem_hof' |
|
69 | 69 | end |
|
70 | 70 | append_to menu_items, "[#{I18n.t 'menu.help'}]", 'main', 'help' |
|
71 | 71 | |
|
72 | 72 | if GraderConfiguration['system.user_setting_enabled'] |
|
73 | 73 | append_to menu_items, "[#{I18n.t 'menu.settings'}]", 'users', 'index' |
|
74 | 74 | end |
|
75 | 75 | append_to menu_items, "[#{I18n.t 'menu.log_out'}]", 'main', 'login' |
|
76 | 76 | |
|
77 | 77 | menu_items.html_safe |
|
78 | 78 | end |
|
79 | 79 | |
|
80 | 80 | def append_to(option,label, controller, action) |
|
81 | 81 | option << ' ' if option!='' |
|
82 | 82 | option << link_to_unless_current(label, |
|
83 | 83 | :controller => controller, |
|
84 | 84 | :action => action) |
|
85 | 85 | end |
|
86 | 86 | |
|
87 | 87 | def format_short_time(time) |
|
88 | 88 | now = Time.zone.now |
|
89 | 89 | st = '' |
|
90 | 90 | if (time.yday != now.yday) or (time.year != now.year) |
|
91 | 91 | st = time.strftime("%d/%m/%y ") |
|
92 | 92 | end |
|
93 | 93 | st + time.strftime("%X") |
|
94 | 94 | end |
|
95 | 95 | |
|
96 | 96 | def format_short_duration(duration) |
|
97 | 97 | return '' if duration==nil |
|
98 | 98 | d = duration.to_f |
|
99 | 99 | return Time.at(d).gmtime.strftime("%X") |
|
100 | 100 | end |
|
101 | 101 | |
|
102 | 102 | def format_full_time_ago(time) |
|
103 | 103 | st = time_ago_in_words(time) + ' ago (' + format_short_time(time) + ')' |
|
104 | 104 | end |
|
105 | 105 | |
|
106 | 106 | def read_textfile(fname,max_size=2048) |
|
107 | 107 | begin |
|
108 | 108 | File.open(fname).read(max_size) |
|
109 | 109 | rescue |
|
110 | 110 | nil |
|
111 | 111 | end |
|
112 | 112 | end |
|
113 | 113 | |
|
114 | 114 | def toggle_button(on,toggle_url,id, option={}) |
|
115 | 115 | btn_size = option[:size] || 'btn-xs' |
|
116 | 116 | btn_block = option[:block] || 'btn-block' |
|
117 | 117 | link_to (on ? "Yes" : "No"), toggle_url, |
|
118 | 118 | {class: "btn #{btn_block} #{btn_size} btn-#{on ? 'success' : 'default'} ajax-toggle", |
|
119 | 119 | id: id, |
|
120 | 120 | data: {remote: true, method: 'get'}} |
|
121 | 121 | end |
|
122 | 122 | |
|
123 | 123 | def get_ace_mode(language) |
|
124 | 124 | # return ace mode string from Language |
|
125 | 125 | |
|
126 | 126 | case language.pretty_name |
|
127 | 127 | when 'Pascal' |
|
128 | 128 | 'ace/mode/pascal' |
|
129 | 129 | when 'C++','C' |
|
130 | 130 | 'ace/mode/c_cpp' |
|
131 | 131 | when 'Ruby' |
|
132 | 132 | 'ace/mode/ruby' |
|
133 | 133 | when 'Python' |
|
134 | 134 | 'ace/mode/python' |
|
135 | 135 | when 'Java' |
|
136 | 136 | 'ace/mode/java' |
|
137 | 137 | else |
|
138 | 138 | 'ace/mode/c_cpp' |
|
139 | 139 | end |
|
140 | 140 | end |
|
141 | 141 | |
|
142 | 142 | |
|
143 | 143 | def user_title_bar(user) |
|
144 | 144 | header = '' |
|
145 | 145 | time_left = '' |
|
146 | 146 | |
|
147 | 147 | # |
|
148 | 148 | # if the contest is over |
|
149 | 149 | if GraderConfiguration.time_limit_mode? |
|
150 | 150 | if user.contest_finished? |
|
151 | 151 | header = <<CONTEST_OVER |
|
152 | 152 | <tr><td colspan="2" align="center"> |
|
153 | 153 | <span class="contest-over-msg">THE CONTEST IS OVER</span> |
|
154 | 154 | </td></tr> |
|
155 | 155 | CONTEST_OVER |
|
156 | 156 | end |
|
157 | 157 | if !user.contest_started? |
|
158 | 158 | time_left = " " + (t 'title_bar.contest_not_started') |
|
159 | 159 | else |
|
160 | 160 | time_left = " " + (t 'title_bar.remaining_time') + |
|
161 | 161 | " #{format_short_duration(user.contest_time_left)}" |
|
162 | 162 | end |
|
163 | 163 | end |
|
164 | 164 | |
|
165 | 165 | # |
|
166 | 166 | # if the contest is in the anaysis mode |
|
167 | 167 | if GraderConfiguration.analysis_mode? |
|
168 | 168 | header = <<ANALYSISMODE |
|
169 | 169 | <tr><td colspan="2" align="center"> |
|
170 | 170 | <span class="contest-over-msg">ANALYSIS MODE</span> |
|
171 | 171 | </td></tr> |
|
172 | 172 | ANALYSISMODE |
|
173 | 173 | end |
|
174 | 174 | |
|
175 | 175 | contest_name = GraderConfiguration['contest.name'] |
|
176 | 176 | |
|
177 | 177 | # |
|
178 | 178 | # build real title bar |
|
179 | 179 | result = <<TITLEBAR |
|
180 | 180 | <div class="title"> |
|
181 | 181 | <table> |
|
182 | 182 | #{header} |
|
183 | 183 | <tr> |
|
184 | 184 | <td class="left-col"> |
|
185 | - #{user.full_name}<br/> | |
|
186 | - #{t 'title_bar.current_time'} #{format_short_time(Time.zone.now)} | |
|
187 | - #{time_left} | |
|
188 | 185 | <br/> |
|
189 | 186 | </td> |
|
190 | 187 | <td class="right-col">#{contest_name}</td> |
|
191 | 188 | </tr> |
|
192 | 189 | </table> |
|
193 | 190 | </div> |
|
194 | 191 | TITLEBAR |
|
195 | 192 | result.html_safe |
|
196 | 193 | end |
|
197 | 194 | |
|
198 | 195 | def markdown(text) |
|
199 | 196 | markdown = RDiscount.new(text) |
|
200 | 197 | markdown.to_html.html_safe |
|
201 | 198 | end |
|
202 | 199 | |
|
203 | 200 | |
|
204 | 201 | BOOTSTRAP_FLASH_MSG = { |
|
205 | 202 | success: 'alert-success', |
|
206 | 203 | error: 'alert-danger', |
|
207 | 204 | alert: 'alert-danger', |
|
208 | 205 | notice: 'alert-info' |
|
209 | 206 | } |
|
210 | 207 | |
|
211 | 208 | def bootstrap_class_for(flash_type) |
|
212 | 209 | BOOTSTRAP_FLASH_MSG.fetch(flash_type.to_sym, flash_type.to_s) |
|
213 | 210 | end |
|
214 | 211 | |
|
215 | 212 | def flash_messages |
|
216 | 213 | flash.each do |msg_type, message| |
|
217 | 214 | concat(content_tag(:div, message, class: "alert #{bootstrap_class_for(msg_type)} fade in") do |
|
218 | 215 | concat content_tag(:button, 'x', class: "close", data: { dismiss: 'alert' }) |
|
219 | 216 | concat message |
|
220 | 217 | end) |
|
221 | 218 | end |
|
222 | 219 | nil |
|
223 | 220 | end |
|
224 | 221 | |
|
225 | 222 | end |
@@ -1,20 +1,14 | |||
|
1 | 1 | module MainHelper |
|
2 | 2 | |
|
3 |
- def link_to_description_if_any(name, problem |
|
|
3 | + def link_to_description_if_any(name, problem) | |
|
4 | 4 | if !problem.url.blank? |
|
5 |
- return link_to name, problem.url |
|
|
5 | + return link_to name, problem.url | |
|
6 | 6 | elsif !problem.description_filename.blank? |
|
7 | - #build a link to a problem (via task controller) | |
|
8 | 7 | basename, ext = problem.description_filename.split('.') |
|
9 | - options[:controller] = 'tasks' | |
|
10 | - options[:action] = 'download' | |
|
11 | - options[:id] = problem.id | |
|
12 | - options[:file] = basename | |
|
13 | - options[:ext] = ext | |
|
14 | - return link_to name, options | |
|
8 | + return link_to name, download_task_path(problem.id,basename,ext), target: '_blank' | |
|
15 | 9 | else |
|
16 | 10 | return '' |
|
17 | 11 | end |
|
18 | 12 | end |
|
19 | 13 | |
|
20 | 14 | end |
@@ -1,112 +1,113 | |||
|
1 | 1 | %h1= "Submission: #{@submission.id}" |
|
2 | 2 | |
|
3 | 3 | %textarea#data{style: "display:none;"} |
|
4 | 4 | :preserve |
|
5 | 5 | #{@submission.source} |
|
6 | 6 | |
|
7 | 7 | //%div.highlight{:style => "border: 1px solid black;"} |
|
8 | 8 | //=@formatted_code.html_safe |
|
9 | 9 | |
|
10 | 10 | |
|
11 | 11 | .containter |
|
12 | 12 | .row |
|
13 | 13 | .col-md-7 |
|
14 | 14 | %h2 Source Code |
|
15 | 15 | .col-md-5 |
|
16 | 16 | %h2 Stat |
|
17 | 17 | .row |
|
18 | 18 | .col-md-7 |
|
19 | 19 | %div#editor{ style: "font-size: 14px; height: 400px; border-radius:5px;" } |
|
20 | 20 | :javascript |
|
21 | 21 | e = ace.edit("editor") |
|
22 | 22 | e.setOptions({ maxLines: Infinity }) |
|
23 | 23 | e.setValue($("#data").text()) |
|
24 | 24 | e.gotoLine(1) |
|
25 | 25 | e.getSession().setMode("#{get_ace_mode(@submission.language)}") |
|
26 | 26 | e.setReadOnly(true) |
|
27 | 27 | .col-md-5 |
|
28 | 28 | %table.table.table-striped |
|
29 | 29 | %tr |
|
30 | 30 | %td.text-right |
|
31 | 31 | %strong User |
|
32 | 32 | %td |
|
33 | 33 | - if @submission.user |
|
34 | 34 | = link_to "#{@submission.user.login}", stat_user_path(@submission.user) |
|
35 | 35 | = @submission.user.full_name |
|
36 | 36 | - else |
|
37 | 37 | = "(n/a)" |
|
38 | 38 | %tr |
|
39 | 39 | %td.text-right |
|
40 | 40 | %strong Task |
|
41 | 41 | %td |
|
42 | 42 | - if @submission.problem!=nil |
|
43 | 43 | = link_to "[#{@submission.problem.name}]", stat_problem_path(@submission.problem) |
|
44 | 44 | = @submission.problem.full_name |
|
45 | + = link_to_description_if_any "[download] <span class='glyphicon glyphicon-file'></span>".html_safe, @submission.problem | |
|
45 | 46 | - else |
|
46 | 47 | = "(n/a)" |
|
47 | 48 | %tr |
|
48 | 49 | %td.text-right |
|
49 | 50 | %strong Tries |
|
50 | 51 | %td= @submission.number |
|
51 | 52 | %tr |
|
52 | 53 | %td.text-right |
|
53 | 54 | %strong Language |
|
54 | 55 | %td= @submission.language.pretty_name |
|
55 | 56 | %tr |
|
56 | 57 | %td.text-right |
|
57 | 58 | %strong Submitted |
|
58 | 59 | %td #{time_ago_in_words(@submission.submitted_at)} ago (at #{@submission.submitted_at.to_formatted_s(:long)}) |
|
59 | 60 | %tr |
|
60 | 61 | %td.text-right |
|
61 | 62 | %strong Graded |
|
62 | 63 | - if @submission.graded_at |
|
63 | 64 | %td #{time_ago_in_words(@submission.graded_at)} ago (at #{@submission.graded_at.to_formatted_s(:long)}) |
|
64 | 65 | - else |
|
65 | 66 | %td - |
|
66 | 67 | %tr |
|
67 | 68 | %td.text-right |
|
68 | 69 | %strong Points |
|
69 | 70 | %td #{@submission.points}/#{@submission.try(:problem).try(:full_score)} |
|
70 | 71 | %tr |
|
71 | 72 | %td.text-right |
|
72 | 73 | %strong Comment |
|
73 | 74 | %td #{@submission.grader_comment} |
|
74 | 75 | %tr |
|
75 | 76 | %td.text-right |
|
76 | 77 | %strong Runtime (s) |
|
77 | 78 | %td #{@submission.max_runtime} |
|
78 | 79 | %tr |
|
79 | 80 | %td.text-right |
|
80 | 81 | %strong Memory (kb) |
|
81 | 82 | %td #{@submission.peak_memory} |
|
82 | 83 | %tr |
|
83 | 84 | %td.text-right |
|
84 | 85 | %strong Compiler result |
|
85 | 86 | %td |
|
86 | 87 | %button.btn.btn-info.btn-xs{type: 'button', data: {toggle: 'modal', target: '#compiler'}} |
|
87 | 88 | view |
|
88 | 89 | - if session[:admin] |
|
89 | 90 | %tr |
|
90 | 91 | %td.text-right |
|
91 | 92 | %strong IP |
|
92 | 93 | %td #{@submission.ip_address} |
|
93 | 94 | %tr |
|
94 | 95 | %td.text-right |
|
95 | 96 | %strong Grading Task Status |
|
96 | 97 | %td |
|
97 | 98 | = @task.status_str if @task |
|
98 | 99 | - if session[:admin] |
|
99 | 100 | = link_to "rejudge", rejudge_submission_path, data: {remote: true}, class: 'btn btn-info btn-xs' |
|
100 | 101 | |
|
101 | 102 | |
|
102 | 103 | .modal.fade#compiler{tabindex: -1,role: 'dialog'} |
|
103 | 104 | .modal-dialog.modal-lg{role:'document'} |
|
104 | 105 | .modal-content |
|
105 | 106 | .modal-header |
|
106 | 107 | %button.close{type: 'button', data: {dismissed: :modal}, aria: {label: 'close'}} |
|
107 | 108 | %span{aria: {hidden: 'true'}, data: {dismiss: 'modal'}} × |
|
108 | 109 | %h4 Compiler message |
|
109 | 110 | .modal-body |
|
110 | 111 | %pre#compiler_msg= @submission.compiler_message |
|
111 | 112 | .modal-footer |
|
112 | 113 | %button.btn.btn-default{type: 'button', data: {dismiss: 'modal'}} Close |
@@ -1,45 +1,54 | |||
|
1 | 1 | .container-fluid |
|
2 | 2 | .row |
|
3 | 3 | .col-md-6 |
|
4 | 4 | %h1 Adding list of users |
|
5 | 5 | .row |
|
6 | 6 | .col-md-6 |
|
7 | 7 | .panel.panel-default |
|
8 | 8 | .panel-heading |
|
9 | 9 | .panel-title Info |
|
10 | 10 | .panel-body |
|
11 | 11 | %ul |
|
12 | 12 | %li |
|
13 | 13 | List of user information in this format: |
|
14 | 14 | %tt user_id,name(,passwd(,alias(,remark))) |
|
15 | 15 | %li |
|
16 | 16 | Note that |
|
17 | 17 | %tt passwd, alias |
|
18 | 18 | and |
|
19 | 19 | %tt remark |
|
20 | 20 | is optional. |
|
21 | 21 | %li |
|
22 | 22 | When |
|
23 | 23 | %tt passwd |
|
24 | 24 | or |
|
25 | 25 | %tt alias |
|
26 | 26 | is empty, the original value will be used instead. |
|
27 | 27 | %li |
|
28 | 28 | If the users with the same user_id already exists, existing information will be overwritten. |
|
29 | + Example: | |
|
30 | + %ol | |
|
31 | + %li | |
|
32 | + %pre user1,Somchai Jaidee | |
|
33 | + will create (or update) a user with login "user1" and setting the fullname to "Somchai Jaidee", also setting a random password. | |
|
34 | + %li | |
|
35 | + %pre user1,Somchai Jaidee, | |
|
36 | + will create (or update) a user with login "user1" and and setting the fullname "Somchai Jaidee". No change is made to the password unless this is a new user. If this is a new user, a random password will be generated. | |
|
37 | + | |
|
29 | 38 | |
|
30 | 39 | .row |
|
31 | 40 | .col-md-6 |
|
32 | 41 | = form_tag :action => 'create_from_list' do |
|
33 | 42 | .form-group |
|
34 | 43 | = submit_tag 'Create following users',class: 'btn btn-success' |
|
35 | 44 | .form-group |
|
36 | 45 | .div.checkbox |
|
37 | 46 | %label |
|
38 | 47 | = check_box_tag :add_to_group |
|
39 | 48 | Also add these users to the following group |
|
40 | 49 | = select_tag "group_id", options_from_collection_for_select( Group.all, 'id','name',params[:group_name]), id: 'group_name',class: 'select2' |
|
41 | 50 | .form-group |
|
42 | 51 | = text_area_tag 'user_list', nil, :rows => 50, :cols => 80 |
|
43 | 52 | .col-md-6 |
|
44 | 53 | |
|
45 | 54 |
@@ -1,204 +1,204 | |||
|
1 | 1 | Rails.application.routes.draw do |
|
2 | 2 | resources :tags |
|
3 | 3 | get "sources/direct_edit" |
|
4 | 4 | |
|
5 | 5 | root :to => 'main#login' |
|
6 | 6 | |
|
7 | 7 | #logins |
|
8 | 8 | match 'login/login', to: 'login#login', via: [:get,:post] |
|
9 | 9 | |
|
10 | 10 | resources :contests |
|
11 | 11 | resources :sites |
|
12 | 12 | resources :test |
|
13 | 13 | |
|
14 | 14 | resources :messages do |
|
15 | 15 | member do |
|
16 | 16 | get 'hide' |
|
17 | 17 | post 'reply' |
|
18 | 18 | end |
|
19 | 19 | collection do |
|
20 | 20 | get 'console' |
|
21 | 21 | get 'list_all' |
|
22 | 22 | end |
|
23 | 23 | end |
|
24 | 24 | |
|
25 | 25 | resources :announcements do |
|
26 | 26 | member do |
|
27 | 27 | get 'toggle','toggle_front' |
|
28 | 28 | end |
|
29 | 29 | end |
|
30 | 30 | |
|
31 | 31 | resources :problems do |
|
32 | 32 | member do |
|
33 | 33 | get 'toggle' |
|
34 | 34 | get 'toggle_test' |
|
35 | 35 | get 'toggle_view_testcase' |
|
36 | 36 | get 'stat' |
|
37 | 37 | end |
|
38 | 38 | collection do |
|
39 | 39 | get 'turn_all_off' |
|
40 | 40 | get 'turn_all_on' |
|
41 | 41 | get 'import' |
|
42 | 42 | get 'manage' |
|
43 | 43 | get 'quick_create' |
|
44 | 44 | post 'do_manage' |
|
45 | 45 | post 'do_import' |
|
46 | 46 | end |
|
47 | 47 | end |
|
48 | 48 | |
|
49 | 49 | resources :groups do |
|
50 | 50 | member do |
|
51 | 51 | post 'add_user', to: 'groups#add_user', as: 'add_user' |
|
52 | 52 | delete 'remove_user/:user_id', to: 'groups#remove_user', as: 'remove_user' |
|
53 | 53 | delete 'remove_all_user', to: 'groups#remove_all_user', as: 'remove_all_user' |
|
54 | 54 | post 'add_problem', to: 'groups#add_problem', as: 'add_problem' |
|
55 | 55 | delete 'remove_problem/:problem_id', to: 'groups#remove_problem', as: 'remove_problem' |
|
56 | 56 | delete 'remove_all_problem', to: 'groups#remove_all_problem', as: 'remove_all_problem' |
|
57 | 57 | get 'toggle' |
|
58 | 58 | end |
|
59 | 59 | collection do |
|
60 | 60 | |
|
61 | 61 | end |
|
62 | 62 | end |
|
63 | 63 | |
|
64 | 64 | resources :testcases, only: [] do |
|
65 | 65 | member do |
|
66 | 66 | get 'download_input' |
|
67 | 67 | get 'download_sol' |
|
68 | 68 | end |
|
69 | 69 | collection do |
|
70 | 70 | get 'show_problem/:problem_id(/:test_num)' => 'testcases#show_problem', as: 'show_problem' |
|
71 | 71 | end |
|
72 | 72 | end |
|
73 | 73 | |
|
74 | 74 | resources :grader_configuration, controller: 'configurations' do |
|
75 | 75 | collection do |
|
76 | 76 | get 'set_exam_right(/:value)', action: 'set_exam_right', as: 'set_exam_right' |
|
77 | 77 | end |
|
78 | 78 | end |
|
79 | 79 | |
|
80 | 80 | resources :users do |
|
81 | 81 | member do |
|
82 | 82 | get 'toggle_activate', 'toggle_enable' |
|
83 | 83 | get 'stat' |
|
84 | 84 | end |
|
85 | 85 | collection do |
|
86 | 86 | get 'profile' |
|
87 | 87 | post 'chg_passwd' |
|
88 | 88 | end |
|
89 | 89 | end |
|
90 | 90 | |
|
91 | 91 | resources :submissions do |
|
92 | 92 | member do |
|
93 | 93 | get 'download' |
|
94 | 94 | get 'compiler_msg' |
|
95 | 95 | get 'rejudge' |
|
96 | 96 | end |
|
97 | 97 | collection do |
|
98 | 98 | get 'prob/:problem_id', to: 'submissions#index', as: 'problem' |
|
99 | 99 | get 'direct_edit_problem/:problem_id(/:user_id)', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem' |
|
100 | 100 | get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status' |
|
101 | 101 | end |
|
102 | 102 | end |
|
103 | 103 | |
|
104 | 104 | |
|
105 | 105 | #user admin |
|
106 | 106 | resources :user_admin do |
|
107 | 107 | collection do |
|
108 | 108 | match 'bulk_manage', via: [:get, :post] |
|
109 | 109 | get 'bulk_mail' |
|
110 | 110 | get 'user_stat' |
|
111 | 111 | get 'import' |
|
112 | 112 | get 'new_list' |
|
113 | 113 | get 'admin' |
|
114 | 114 | get 'active' |
|
115 | 115 | get 'mass_mailing' |
|
116 | 116 | get 'revoke_admin' |
|
117 | 117 | post 'grant_admin' |
|
118 | 118 | match 'create_from_list', via: [:get, :post] |
|
119 | 119 | match 'random_all_passwords', via: [:get, :post] |
|
120 | 120 | end |
|
121 | 121 | member do |
|
122 | 122 | get 'clear_last_ip' |
|
123 | 123 | end |
|
124 | 124 | end |
|
125 | 125 | |
|
126 | 126 | resources :contest_management, only: [:index] do |
|
127 | 127 | collection do |
|
128 | 128 | get 'user_stat' |
|
129 | 129 | get 'clear_stat' |
|
130 | 130 | get 'clear_all_stat' |
|
131 | 131 | get 'change_contest_mode' |
|
132 | 132 | end |
|
133 | 133 | end |
|
134 | 134 | |
|
135 | 135 | #get 'user_admin', to: 'user_admin#index' |
|
136 | 136 | #get 'user_admin/bulk_manage', to: 'user_admin#bulk_manage', as: 'bulk_manage_user_admin' |
|
137 | 137 | #post 'user_admin', to: 'user_admin#create' |
|
138 | 138 | #delete 'user_admin/:id', to: 'user_admin#destroy', as: 'user_admin_destroy' |
|
139 | 139 | |
|
140 | 140 | #singular resource |
|
141 | 141 | #---- BEWARE ---- singular resource maps to plural controller by default, we can override by provide controller name directly |
|
142 | 142 | #report |
|
143 | 143 | resource :report, only: [], controller: 'report' do |
|
144 | 144 | get 'login' |
|
145 | 145 | get 'multiple_login' |
|
146 | 146 | get 'problem_hof(/:id)', action: 'problem_hof', as: 'problem_hof' |
|
147 | 147 | get 'current_score(/:group_id)', action: 'current_score', as: 'current_score' |
|
148 | 148 | get 'max_score' |
|
149 | 149 | post 'show_max_score' |
|
150 | 150 | get 'stuck' |
|
151 | 151 | get 'cheat_report' |
|
152 | 152 | post 'cheat_report' |
|
153 | 153 | get 'cheat_scruntinize' |
|
154 | 154 | post 'cheat_scruntinize' |
|
155 | 155 | end |
|
156 | 156 | #get 'report/current_score', to: 'report#current_score', as: 'report_current_score' |
|
157 | 157 | #get 'report/problem_hof(/:id)', to: 'report#problem_hof', as: 'report_problem_hof' |
|
158 | 158 | #get "report/login" |
|
159 | 159 | #get 'report/max_score', to: 'report#max_score', as: 'report_max_score' |
|
160 | 160 | #post 'report/show_max_score', to: 'report#show_max_score', as: 'report_show_max_score' |
|
161 | 161 | |
|
162 | 162 | resource :main, only: [], controller: 'main' do |
|
163 | 163 | get 'login' |
|
164 | 164 | get 'logout' |
|
165 | 165 | get 'list' |
|
166 | 166 | get 'submission(/:id)', action: 'submission', as: 'main_submission' |
|
167 | 167 | get 'announcements' |
|
168 | 168 | get 'help' |
|
169 | 169 | post 'submit' |
|
170 | 170 | end |
|
171 | 171 | #main |
|
172 | 172 | #get "main/list" |
|
173 | 173 | #get 'main/submission(/:id)', to: 'main#submission', as: 'main_submission' |
|
174 | 174 | #post 'main/submit', to: 'main#submit' |
|
175 | 175 | #get 'main/announcements', to: 'main#announcements' |
|
176 | 176 | |
|
177 | 177 | |
|
178 | 178 | # |
|
179 | 179 | get 'tasks/view/:file.:ext' => 'tasks#view' |
|
180 | - get 'tasks/download/:id/:file.:ext' => 'tasks#download' | |
|
180 | + get 'tasks/download/:id/:file.:ext' => 'tasks#download', as: 'download_task' | |
|
181 | 181 | get 'heartbeat/:id/edit' => 'heartbeat#edit' |
|
182 | 182 | |
|
183 | 183 | #grader |
|
184 | 184 | get 'graders/list', to: 'graders#list', as: 'grader_list' |
|
185 | 185 | namespace :graders do |
|
186 | 186 | get 'task/:id/:type', action: 'task', as: 'task' |
|
187 | 187 | get 'view/:id/:type', action: 'view', as: 'view' |
|
188 | 188 | get 'clear/:id', action: 'clear', as: 'clear' |
|
189 | 189 | get 'stop' |
|
190 | 190 | get 'stop_all' |
|
191 | 191 | get 'clear_all' |
|
192 | 192 | get 'clear_terminated' |
|
193 | 193 | get 'start_grading' |
|
194 | 194 | get 'start_exam' |
|
195 | 195 | |
|
196 | 196 | end |
|
197 | 197 | |
|
198 | 198 | |
|
199 | 199 | # See how all your routes lay out with "rake routes" |
|
200 | 200 | |
|
201 | 201 | # This is a legacy wild controller route that's not recommended for RESTful applications. |
|
202 | 202 | # Note: This route will make all actions in every controller accessible via GET requests. |
|
203 | 203 | # match ':controller(/:action(/:id))(.:format)', via: [:get, :post] |
|
204 | 204 | end |
You need to be logged in to leave comments.
Login now