Description:
add user profile page listing all submission, permission is by 'right.user_view_submission' add link from users to their profile page
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r431:7654a9f33bc8 - - 6 files changed: 89 inserted, 11 deleted

@@ -0,0 +1,40
1 + - content_for :header do
2 + = javascript_include_tag 'new'
3 +
4 + %script{:type=>"text/javascript"}
5 + $(function () {
6 + $('#submission_table').tablesorter({widgets: ['zebra','filter']});
7 + });
8 +
9 + %h1= @user.full_name + ' Profile'
10 +
11 + %h2 Basic info
12 + <b>Login:</b> #{@user.login} <br/>
13 + <b>Full name:</b> #{@user.full_name} <br />
14 +
15 +
16 + %h2 Problem Stat
17 +
18 + %h2 Submissions
19 +
20 + %table.tablesorter-cafe#submission_table
21 + %thead
22 + %tr
23 + %th ID
24 + %th Problem code
25 + %th Problem name
26 + %th Language
27 + %th Result
28 + %th Score
29 + %tbody
30 + - @submission.each do |s|
31 + %tr
32 + %td= link_to "#{s.id}", controller: "graders", action: "submission", id: s.id
33 + %td= s.problem.name
34 + %td= s.problem.full_name
35 + %td= s.language.pretty_name
36 + %td{style: 'font-family: Droid Sans Mono,Consolas, monospace, mono'}= s.grader_comment
37 + %td= s.points/s.problem.full_score * 100
38 +
39 +
40 +
@@ -6,49 +6,50
6 6
7 7 if GraderConfiguration["right.user_view_submission"]
8 8 return true;
9 9 end
10 10
11 11 admin_authorization
12 12 }
13 13
14 14 def login_stat
15 15 @logins = Array.new
16 16
17 17 date_and_time = '%Y-%m-%d %H:%M'
18 18 begin
19 19 @since_time = DateTime.strptime(params[:since_datetime],date_and_time)
20 20 rescue
21 21 @since_time = DateTime.new(1000,1,1)
22 22 end
23 23 begin
24 24 @until_time = DateTime.strptime(params[:until_datetime],date_and_time)
25 25 rescue
26 26 @until_time = DateTime.new(3000,1,1)
27 27 end
28 28
29 29 User.all.each do |user|
30 - @logins << { login: user.login,
30 + @logins << { id: user.id,
31 + login: user.login,
31 32 full_name: user.full_name,
32 33 count: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
33 34 user.id,@since_time,@until_time)
34 35 .count(:id),
35 36 min: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
36 37 user.id,@since_time,@until_time)
37 38 .minimum(:created_at),
38 39 max: Login.where("user_id = ? AND created_at >= ? AND created_at <= ?",
39 40 user.id,@since_time,@until_time)
40 41 .maximum(:created_at)
41 42 }
42 43 end
43 44 end
44 45
45 46 def submission_stat
46 47
47 48 date_and_time = '%Y-%m-%d %H:%M'
48 49 begin
49 50 @since_time = DateTime.strptime(params[:since_datetime],date_and_time)
50 51 rescue
51 52 @since_time = DateTime.new(1000,1,1)
52 53 end
53 54 begin
54 55 @until_time = DateTime.strptime(params[:until_datetime],date_and_time)
@@ -1,40 +1,41
1 1 require 'net/smtp'
2 2
3 3 class UsersController < ApplicationController
4 4
5 5 include MailHelperMethods
6 6
7 7 before_filter :authenticate, :except => [:new,
8 8 :register,
9 9 :confirm,
10 10 :forget,
11 11 :retrieve_password]
12 12
13 13 before_filter :verify_online_registration, :only => [:new,
14 14 :register,
15 15 :forget,
16 16 :retrieve_password]
17 + before_filter :authenticate, :profile_authorization, only: [:profile]
17 18
18 19 verify :method => :post, :only => [:chg_passwd],
19 20 :redirect_to => { :action => :index }
20 21
21 22 #in_place_edit_for :user, :alias_for_editing
22 23 #in_place_edit_for :user, :email_for_editing
23 24
24 25 def index
25 26 if !GraderConfiguration['system.user_setting_enabled']
26 27 redirect_to :controller => 'main', :action => 'list'
27 28 else
28 29 @user = User.find(session[:user_id])
29 30 end
30 31 end
31 32
32 33 def chg_passwd
33 34 user = User.find(session[:user_id])
34 35 user.password = params[:passwd]
35 36 user.password_confirmation = params[:passwd_verify]
36 37 if user.save
37 38 flash[:notice] = 'password changed'
38 39 else
39 40 flash[:notice] = 'Error: password changing failed'
40 41 end
@@ -87,70 +88,89
87 88
88 89 def forget
89 90 render :action => 'forget', :layout => 'empty'
90 91 end
91 92
92 93 def retrieve_password
93 94 email = params[:email]
94 95 user = User.find_by_email(email)
95 96 if user
96 97 last_updated_time = user.updated_at || user.created_at || (Time.now.gmtime - 1.hour)
97 98 if last_updated_time > Time.now.gmtime - 5.minutes
98 99 flash[:notice] = 'The account has recently created or new password has recently been requested. Please wait for 5 minutes'
99 100 else
100 101 user.password = user.password_confirmation = User.random_password
101 102 user.save
102 103 send_new_password_email(user)
103 104 flash[:notice] = 'New password has been mailed to you.'
104 105 end
105 106 else
106 107 flash[:notice] = I18n.t 'registration.password_retrieval.no_email'
107 108 end
108 109 redirect_to :action => 'forget'
109 110 end
110 111
112 + def profile
113 + @user = User.find(params[:id])
114 + @submission = Submission.where(user_id: params[:id]).all
115 + end
116 +
111 117 protected
112 118
113 119 def verify_online_registration
114 120 if !GraderConfiguration['system.online_registration']
115 121 redirect_to :controller => 'main', :action => 'login'
116 122 end
117 123 end
118 124
119 125 def send_confirmation_email(user)
120 126 contest_name = GraderConfiguration['contest.name']
121 127 activation_url = url_for(:action => 'confirm',
122 128 :login => user.login,
123 129 :activation => user.activation_key)
124 130 home_url = url_for(:controller => 'main', :action => 'index')
125 131 mail_subject = "[#{contest_name}] Confirmation"
126 132 mail_body = t('registration.email_body', {
127 133 :full_name => user.full_name,
128 134 :contest_name => contest_name,
129 135 :login => user.login,
130 136 :password => user.password,
131 137 :activation_url => activation_url,
132 138 :admin_email => admin_email
133 139 })
134 140
135 141 logger.info mail_body
136 142
137 143 send_mail(user.email, mail_subject, mail_body)
138 144 end
139 145
140 146 def send_new_password_email(user)
141 147 contest_name = GraderConfiguration['contest.name']
142 148 mail_subject = "[#{contest_name}] Password recovery"
143 149 mail_body = t('registration.password_retrieval.email_body', {
144 150 :full_name => user.full_name,
145 151 :contest_name => contest_name,
146 152 :login => user.login,
147 153 :password => user.password,
148 154 :admin_email => admin_email
149 155 })
150 156
151 157 logger.info mail_body
152 158
153 159 send_mail(user.email, mail_subject, mail_body)
154 160 end
155 161
162 + # allow viewing of regular user profile only when options allow so
163 + # only admins can view admins profile
164 + def profile_authorization
165 + #if view admins' profile, allow only admin
166 + return false unless(params[:id])
167 + user = User.find(params[:id])
168 + return false unless user
169 + return admin_authorization if user.admin?
170 + return true if GraderConfiguration["right.user_view_submission"]
171 +
172 + #finally, we allow only admin
173 + admin_authorization
156 174 end
175 +
176 + end
@@ -1,62 +1,79
1 1 :css
2 2 .hof_user { color: orangered; font-style: italic; }
3 3 .hof_language { color: green; font-style: italic; }
4 4 .hof_value { color: deeppink;font-style: italic; }
5 5
6 6 %h2 Overall
7 7
8 8 - if @best
9 9 %b Best Runtime:
10 - by <span class="hof_user">#{@best[:runtime][:user]}</span> using <span class="hof_language">#{@best[:runtime][:lang]}</span> with <span class="hof_value">#{@best[:runtime][:value] * 1000} milliseconds</span> at submission
10 + by #{link_to @best[:runtime][:user], controller:'users', action:'profile', id:@best[:memory][:user_id]}
11 + using <span class="hof_language">#{@best[:runtime][:lang]}</span>
12 + with <span class="hof_value">#{@best[:runtime][:value] * 1000} milliseconds</span>
13 + at submission
11 14 = link_to("#" + @best[:runtime][:sub_id].to_s, controller: 'graders', action: 'submission', id:@best[:runtime][:sub_id])
12 15 %br/
13 16
14 17 %b Best Memory Usage:
15 - by <span class="hof_user">#{@best[:memory][:user]}</span> using <span class="hof_language">#{@best[:memory][:lang]}</span> with <span class="hof_value">#{@best[:memory][:value]} kbytes </span> at submission
18 + by #{link_to @best[:memory][:user], controller:'users', action:'profile', id:@best[:memory][:user_id]}
19 + using <span class="hof_language">#{@best[:memory][:lang]}</span>
20 + with <span class="hof_value">#{@best[:memory][:value]} kbytes </span>
21 + at submission
16 22 = link_to("#" + @best[:memory][:sub_id].to_s, controller: 'graders' , action: 'submission', id:@best[:memory][:sub_id])
17 23 %br/
18 24
19 25 %b Shortest Code:
20 - by <span class="hof_user">#{@best[:length][:user]}</span> using <span class="hof_language">#{@best[:length][:lang]}</span> with <span class="hof_value">#{@best[:length][:value]} bytes</span> at submission
26 + by #{link_to @best[:length][:user], controller:'users', action:'profile', id:@best[:length][:user_id]}
27 + using <span class="hof_language">#{@best[:length][:lang]}</span>
28 + with <span class="hof_value">#{@best[:length][:value]} bytes</span>
29 + at submission
21 30 = link_to("#" + @best[:length][:sub_id].to_s, controller: 'graders' , action: 'submission', id: @best[:length][:sub_id])
22 31 %br/
23 32
24 33 %b First solver:
25 - <span class="hof_user">#{@best[:first][:user]}</span> is the first solver using <span class="hof_language">#{@best[:first][:lang]}</span> on <span class="hof_value">#{@best[:first][:value]}</span> at submission
34 + #{link_to @best[:first][:user], controller:'users', action:'profile', id:@best[:first][:user_id]} is the first solver
35 + using <span class="hof_language">#{@best[:first][:lang]}</span>
36 + on <span class="hof_value">#{@best[:first][:value]}</span>
37 + at submission
26 38 = link_to("#" + @best[:first][:sub_id].to_s, controller: 'graders' , action: 'submission', id: @best[:first][:sub_id])
27 39 %br/
28 40
29 41
30 42 %p
31 43 This counts only for submission with 100% score <br/>
32 44 Right now, java is excluded from memory usage competition. (Because it always uses 2GB memory...)
33 45
34 46 %h2 By language
35 47
36 48 %table.info
37 49 %thead
38 50 %tr.info-head
39 51 %th Language
40 52 %th Best runtime (ms)
41 53 %th Best memory (kbytes)
42 54 %th Shortest Code (bytes)
43 55 %th First solver
44 56 %tbody
45 57 - @by_lang.each do |lang,value|
46 58 %tr{class: cycle('info-even','info-odd')}
47 59 %td= lang
48 60 %td
49 - = "#{value[:runtime][:user]} (#{(value[:runtime][:value] * 1000).to_i} @"
61 + = link_to value[:runtime][:user], controller: 'users', action: 'profile', id: value[:runtime][:user_id]
62 + = "(#{(value[:runtime][:value] * 1000).to_i} @"
50 63 = "#{link_to("#" + value[:runtime][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:runtime][:sub_id])} )".html_safe
51 64 %td
52 - = "#{value[:memory][:user]} (#{value[:memory][:value]} @"
65 + = link_to value[:memory][:user], controller: 'users', action: 'profile', id: value[:memory][:user_id]
66 + = "(#{value[:memory][:value]} @"
53 67 = "#{link_to("#" + value[:memory][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:memory][:sub_id])} )".html_safe
54 68 %td
55 - = "#{value[:length][:user]} (#{value[:length][:value]} @"
69 + = link_to value[:length][:user], controller: 'users', action: 'profile', id: value[:length][:user_id]
70 + = "(#{value[:length][:value]} @"
56 71 = "#{link_to("#" + value[:length][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:length][:sub_id])} )".html_safe
57 72 %td
58 - = "#{value[:first][:user]} (#{value[:first][:value]} @"
73 + - if value[:first][:user] != '(NULL)' #TODO: i know... this is wrong...
74 + = link_to value[:first][:user], controller: 'users', action: 'profile', id: value[:first][:user_id]
75 + = "(#{value[:first][:value]} @"
59 76 = "#{link_to("#" + value[:first][:sub_id].to_s, controller: 'graders' , action: 'submission', id: value[:first][:sub_id])} )".html_safe
60 77
61 78 - else
62 79 %h3 No submissions
@@ -4,29 +4,29
4 4
5 5 %script{:type=>"text/javascript"}
6 6 $(function () {
7 7 $('#since_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
8 8 $('#until_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
9 9 $('#my_table').tablesorter({widthFixed: true, widgets: ['zebra']});
10 10 });
11 11
12 12 %h1 Login status
13 13
14 14 =render partial: 'report_menu'
15 15 =render partial: 'date_range', locals: {param_text: 'Login date range:', title: 'Query login stat in the range' }
16 16
17 17 %table.tablesorter-cafe#my_table
18 18 %thead
19 19 %tr
20 20 %th login
21 21 %th full name
22 22 %th login count
23 23 %th earliest
24 24 %th latest
25 25 %tbody
26 26 - @logins.each do |l|
27 27 %tr{class: cycle('info-even','info-odd')}
28 - %td= l[:login]
28 + %td= link_to l[:login], controller: 'users', action: 'profile', id: l[:id]
29 29 %td= l[:full_name]
30 30 %td= l[:count]
31 31 %td= l[:min] ? l[:min].in_time_zone.strftime('%Y-%m-%d %H:%M') : ''
32 32 %td= l[:max] ? time_ago_in_words(l[:max].in_time_zone) + ' ago' : ''
@@ -20,35 +20,35
20 20
21 21 - if params[:action] == 'user_stat'
22 22 = "latest score"
23 23 - else
24 24 = link_to '[Show only latest submissions]', controller: :user_admin, action: :user_stat
25 25
26 26 %table.tablesorter-cafe#my_table
27 27 %thead
28 28 %tr
29 29 %th User
30 30 %th Name
31 31 %th Activated?
32 32 %th Logged in
33 33 %th Contest(s)
34 34 - @problems.each do |p|
35 35 %th= p.name
36 36 %th Total
37 37 %th Passed
38 38 %tbody
39 39 - @scorearray.each do |sc|
40 40 %tr{class: cycle('info-even','info-odd')}
41 41 - total,num_passed = 0,0
42 42 - sc.each_index do |i|
43 43 - if i == 0
44 - %td= sc[i].login
44 + %td= link_to sc[i].login, controller: 'users', action: 'profile', id: sc[i]
45 45 %td= sc[i].full_name
46 46 %td= sc[i].activated
47 47 %td= sc[i].try(:contest_stat).try(:started_at)!=nil ? 'yes' : 'no'
48 48 %td= sc[i].contests.collect {|c| c.name}.join(', ')
49 49 - else
50 50 %td= sc[i][0]
51 51 - total += sc[i][0]
52 52 - num_passed += 1 if sc[i][1]
53 53 %td= total
54 54 %td= num_passed
You need to be logged in to leave comments. Login now