Description:
merge
Commit status:
[Not Reviewed]
References:
merge java
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r513:3968658b7a13 - - 13 files changed: 88 inserted, 65 deleted

@@ -0,0 +1,13
1 + = user_title_bar(@user)
2 +
3 + %h1 Console: all messages
4 +
5 + = link_to '[active messages]', :action => 'list_all'
6 +
7 + %table
8 + %tr
9 + %th From
10 + %th When
11 + %th Message
12 + %th
13 + = render :partial => "short_message", :collection => @messages
file renamed from app/assets/javascripts/new.js to app/assets/javascripts/local_jquery.js
@@ -1,80 +1,85
1 class MessagesController < ApplicationController
1 class MessagesController < ApplicationController
2
2
3 before_filter :authenticate
3 before_filter :authenticate
4
4
5 verify :method => :post, :only => ['create'],
5 verify :method => :post, :only => ['create'],
6 :redirect_to => { :action => 'list' }
6 :redirect_to => { :action => 'list' }
7
7
8 before_filter :admin_authorization, :only => ['console','show',
8 before_filter :admin_authorization, :only => ['console','show',
9 - 'reply','hide']
9 + 'reply','hide','list_all']
10
10
11 def list
11 def list
12 @user = User.find(session[:user_id])
12 @user = User.find(session[:user_id])
13 @messages = Message.find_all_sent_by_user(@user)
13 @messages = Message.find_all_sent_by_user(@user)
14 end
14 end
15 -
15 +
16 def console
16 def console
17 @user = User.find(session[:user_id])
17 @user = User.find(session[:user_id])
18 @messages = Message.find_all_system_unreplied_messages
18 @messages = Message.find_all_system_unreplied_messages
19 end
19 end
20
20
21 def show
21 def show
22 @message = Message.find(params[:id])
22 @message = Message.find(params[:id])
23 end
23 end
24
24
25 + def list_all
26 + @user = User.find(session[:user_id])
27 + @messages = Message.where(receiver_id: nil).order(:created_at)
28 + end
29 +
25 def create
30 def create
26 user = User.find(session[:user_id])
31 user = User.find(session[:user_id])
27 @message = Message.new(params[:message])
32 @message = Message.new(params[:message])
28 @message.sender = user
33 @message.sender = user
29 if !@message.save
34 if !@message.save
30 render :action => 'list' and return
35 render :action => 'list' and return
31 else
36 else
32 flash[:notice] = 'New message posted'
37 flash[:notice] = 'New message posted'
33 redirect_to :action => 'list'
38 redirect_to :action => 'list'
34 end
39 end
35 end
40 end
36
41
37 def reply
42 def reply
38 user = User.find(session[:user_id])
43 user = User.find(session[:user_id])
39 @message = Message.new(params[:r_message])
44 @message = Message.new(params[:r_message])
40 @message.sender = user
45 @message.sender = user
41 if !@message.save
46 if !@message.save
42 render :action => 'show' and return
47 render :action => 'show' and return
43 else
48 else
44 flash[:notice] = 'Message replied'
49 flash[:notice] = 'Message replied'
45 rep_msg = @message.replying_message
50 rep_msg = @message.replying_message
46 rep_msg.replied = true
51 rep_msg.replied = true
47 rep_msg.save
52 rep_msg.save
48 redirect_to :action => 'console'
53 redirect_to :action => 'console'
49 end
54 end
50 end
55 end
51
56
52 def hide
57 def hide
53 message = Message.find(params[:id])
58 message = Message.find(params[:id])
54 message.replied = true
59 message.replied = true
55 message.save
60 message.save
56 flash[:notice] = 'Message hided (just marked replied)'
61 flash[:notice] = 'Message hided (just marked replied)'
57 redirect_to :action => 'console'
62 redirect_to :action => 'console'
58 end
63 end
59
64
60 protected
65 protected
61 def build_replying_message_hierarchy(user)
66 def build_replying_message_hierarchy(user)
62 @all_messages = {}
67 @all_messages = {}
63
68
64
69
65 # manually build replies hierarchy (to improve efficiency)
70 # manually build replies hierarchy (to improve efficiency)
66 [@messages, @replied_messages].each do |collection|
71 [@messages, @replied_messages].each do |collection|
67 collection.each do |m|
72 collection.each do |m|
68 @all_messages[m.id] = {:msg => m, :replies => []}
73 @all_messages[m.id] = {:msg => m, :replies => []}
69 end
74 end
70 end
75 end
71
76
72 @all_messages.each do |m|
77 @all_messages.each do |m|
73 rep_id = m.replying_message_id
78 rep_id = m.replying_message_id
74 if @all_messages[rep_id]!=nil
79 if @all_messages[rep_id]!=nil
75 @all_messages[rep_id][:replies] << m
80 @all_messages[rep_id][:replies] << m
76 end
81 end
77 end
82 end
78 end
83 end
79
84
80 end
85 end
@@ -71,178 +71,190
71 def edit
71 def edit
72 @problem = Problem.find(params[:id])
72 @problem = Problem.find(params[:id])
73 @description = @problem.description
73 @description = @problem.description
74 end
74 end
75
75
76 def update
76 def update
77 @problem = Problem.find(params[:id])
77 @problem = Problem.find(params[:id])
78 @description = @problem.description
78 @description = @problem.description
79 if @description == nil and params[:description][:body]!=''
79 if @description == nil and params[:description][:body]!=''
80 @description = Description.new(params[:description])
80 @description = Description.new(params[:description])
81 if !@description.save
81 if !@description.save
82 flash[:notice] = 'Error saving description'
82 flash[:notice] = 'Error saving description'
83 render :action => 'edit' and return
83 render :action => 'edit' and return
84 end
84 end
85 @problem.description = @description
85 @problem.description = @description
86 elsif @description!=nil
86 elsif @description!=nil
87 if !@description.update_attributes(params[:description])
87 if !@description.update_attributes(params[:description])
88 flash[:notice] = 'Error saving description'
88 flash[:notice] = 'Error saving description'
89 render :action => 'edit' and return
89 render :action => 'edit' and return
90 end
90 end
91 end
91 end
92 if params[:file] and params[:file].content_type != 'application/pdf'
92 if params[:file] and params[:file].content_type != 'application/pdf'
93 flash[:notice] = 'Error: Uploaded file is not PDF'
93 flash[:notice] = 'Error: Uploaded file is not PDF'
94 render :action => 'edit' and return
94 render :action => 'edit' and return
95 end
95 end
96 if @problem.update_attributes(params[:problem])
96 if @problem.update_attributes(params[:problem])
97 flash[:notice] = 'Problem was successfully updated.'
97 flash[:notice] = 'Problem was successfully updated.'
98 unless params[:file] == nil or params[:file] == ''
98 unless params[:file] == nil or params[:file] == ''
99 flash[:notice] = 'Problem was successfully updated and a new PDF file is uploaded.'
99 flash[:notice] = 'Problem was successfully updated and a new PDF file is uploaded.'
100 out_dirname = "#{Problem.download_file_basedir}/#{@problem.id}"
100 out_dirname = "#{Problem.download_file_basedir}/#{@problem.id}"
101 if not FileTest.exists? out_dirname
101 if not FileTest.exists? out_dirname
102 Dir.mkdir out_dirname
102 Dir.mkdir out_dirname
103 end
103 end
104
104
105 out_filename = "#{out_dirname}/#{@problem.name}.pdf"
105 out_filename = "#{out_dirname}/#{@problem.name}.pdf"
106 if FileTest.exists? out_filename
106 if FileTest.exists? out_filename
107 File.delete out_filename
107 File.delete out_filename
108 end
108 end
109
109
110 File.open(out_filename,"wb") do |file|
110 File.open(out_filename,"wb") do |file|
111 file.write(params[:file].read)
111 file.write(params[:file].read)
112 end
112 end
113 @problem.description_filename = "#{@problem.name}.pdf"
113 @problem.description_filename = "#{@problem.name}.pdf"
114 @problem.save
114 @problem.save
115 end
115 end
116 redirect_to :action => 'show', :id => @problem
116 redirect_to :action => 'show', :id => @problem
117 else
117 else
118 render :action => 'edit'
118 render :action => 'edit'
119 end
119 end
120 end
120 end
121
121
122 def destroy
122 def destroy
123 Problem.find(params[:id]).destroy
123 Problem.find(params[:id]).destroy
124 redirect_to :action => 'list'
124 redirect_to :action => 'list'
125 end
125 end
126
126
127 def toggle
127 def toggle
128 @problem = Problem.find(params[:id])
128 @problem = Problem.find(params[:id])
129 @problem.available = !(@problem.available)
129 @problem.available = !(@problem.available)
130 @problem.save
130 @problem.save
131 end
131 end
132
132
133 def turn_all_off
133 def turn_all_off
134 Problem.find(:all,
134 Problem.find(:all,
135 :conditions => "available = 1").each do |problem|
135 :conditions => "available = 1").each do |problem|
136 problem.available = false
136 problem.available = false
137 problem.save
137 problem.save
138 end
138 end
139 redirect_to :action => 'list'
139 redirect_to :action => 'list'
140 end
140 end
141
141
142 def turn_all_on
142 def turn_all_on
143 Problem.find(:all,
143 Problem.find(:all,
144 :conditions => "available = 0").each do |problem|
144 :conditions => "available = 0").each do |problem|
145 problem.available = true
145 problem.available = true
146 problem.save
146 problem.save
147 end
147 end
148 redirect_to :action => 'list'
148 redirect_to :action => 'list'
149 end
149 end
150
150
151 def stat
151 def stat
152 @problem = Problem.find(params[:id])
152 @problem = Problem.find(params[:id])
153 if !@problem.available
153 if !@problem.available
154 redirect_to :controller => 'main', :action => 'list'
154 redirect_to :controller => 'main', :action => 'list'
155 else
155 else
156 @submissions = Submission.includes(:user).where(problem_id: params[:id]).order(:user_id,:id)
156 @submissions = Submission.includes(:user).where(problem_id: params[:id]).order(:user_id,:id)
157 end
157 end
158 end
158 end
159
159
160 def manage
160 def manage
161 @problems = Problem.find(:all, :order => 'date_added DESC')
161 @problems = Problem.find(:all, :order => 'date_added DESC')
162 end
162 end
163
163
164 def do_manage
164 def do_manage
165 if params.has_key? 'change_date_added'
165 if params.has_key? 'change_date_added'
166 change_date_added
166 change_date_added
167 - else params.has_key? 'add_to_contest'
167 + elsif params.has_key? 'add_to_contest'
168 add_to_contest
168 add_to_contest
169 + elsif params.has_key? 'enable_problem'
170 + set_available(true)
171 + elsif params.has_key? 'disable_problem'
172 + set_available(false)
169 end
173 end
170 redirect_to :action => 'manage'
174 redirect_to :action => 'manage'
171 end
175 end
172
176
173 def import
177 def import
174 @allow_test_pair_import = allow_test_pair_import?
178 @allow_test_pair_import = allow_test_pair_import?
175 end
179 end
176
180
177 def do_import
181 def do_import
178 old_problem = Problem.find_by_name(params[:name])
182 old_problem = Problem.find_by_name(params[:name])
179 if !allow_test_pair_import? and params.has_key? :import_to_db
183 if !allow_test_pair_import? and params.has_key? :import_to_db
180 params.delete :import_to_db
184 params.delete :import_to_db
181 end
185 end
182 @problem, import_log = Problem.create_from_import_form_params(params,
186 @problem, import_log = Problem.create_from_import_form_params(params,
183 old_problem)
187 old_problem)
184
188
185 if !@problem.errors.empty?
189 if !@problem.errors.empty?
186 render :action => 'import' and return
190 render :action => 'import' and return
187 end
191 end
188
192
189 if old_problem!=nil
193 if old_problem!=nil
190 flash[:notice] = "The test data has been replaced for problem #{@problem.name}"
194 flash[:notice] = "The test data has been replaced for problem #{@problem.name}"
191 end
195 end
192 @log = import_log
196 @log = import_log
193 end
197 end
194
198
195 def remove_contest
199 def remove_contest
196 problem = Problem.find(params[:id])
200 problem = Problem.find(params[:id])
197 contest = Contest.find(params[:contest_id])
201 contest = Contest.find(params[:contest_id])
198 if problem!=nil and contest!=nil
202 if problem!=nil and contest!=nil
199 problem.contests.delete(contest)
203 problem.contests.delete(contest)
200 end
204 end
201 redirect_to :action => 'manage'
205 redirect_to :action => 'manage'
202 end
206 end
203
207
204 ##################################
208 ##################################
205 protected
209 protected
206
210
207 def allow_test_pair_import?
211 def allow_test_pair_import?
208 if defined? ALLOW_TEST_PAIR_IMPORT
212 if defined? ALLOW_TEST_PAIR_IMPORT
209 return ALLOW_TEST_PAIR_IMPORT
213 return ALLOW_TEST_PAIR_IMPORT
210 else
214 else
211 return false
215 return false
212 end
216 end
213 end
217 end
214
218
215 def change_date_added
219 def change_date_added
216 problems = get_problems_from_params
220 problems = get_problems_from_params
217 year = params[:date_added][:year].to_i
221 year = params[:date_added][:year].to_i
218 month = params[:date_added][:month].to_i
222 month = params[:date_added][:month].to_i
219 day = params[:date_added][:day].to_i
223 day = params[:date_added][:day].to_i
220 date = Date.new(year,month,day)
224 date = Date.new(year,month,day)
221 problems.each do |p|
225 problems.each do |p|
222 p.date_added = date
226 p.date_added = date
223 p.save
227 p.save
224 end
228 end
225 end
229 end
226
230
227 def add_to_contest
231 def add_to_contest
228 problems = get_problems_from_params
232 problems = get_problems_from_params
229 contest = Contest.find(params[:contest][:id])
233 contest = Contest.find(params[:contest][:id])
230 if contest!=nil and contest.enabled
234 if contest!=nil and contest.enabled
231 problems.each do |p|
235 problems.each do |p|
232 p.contests << contest
236 p.contests << contest
233 end
237 end
234 end
238 end
235 end
239 end
236
240
241 + def set_available(avail)
242 + problems = get_problems_from_params
243 + problems.each do |p|
244 + p.available = avail
245 + p.save
246 + end
247 + end
248 +
237 def get_problems_from_params
249 def get_problems_from_params
238 problems = []
250 problems = []
239 params.keys.each do |k|
251 params.keys.each do |k|
240 if k.index('prob-')==0
252 if k.index('prob-')==0
241 - name, id = k.split('-')
253 + name, id, order = k.split('-')
242 problems << Problem.find(id)
254 problems << Problem.find(id)
243 end
255 end
244 end
256 end
245 problems
257 problems
246 end
258 end
247
259
248 end
260 end
@@ -1,60 +1,60
1 class Message < ActiveRecord::Base
1 class Message < ActiveRecord::Base
2
2
3 belongs_to :sender, :class_name => "User"
3 belongs_to :sender, :class_name => "User"
4 belongs_to :receiver, :class_name => "User"
4 belongs_to :receiver, :class_name => "User"
5
5
6 belongs_to :replying_message, :class_name => "Message"
6 belongs_to :replying_message, :class_name => "Message"
7
7
8 # commented manually do it
8 # commented manually do it
9 #
9 #
10 #has_many :replied_messages, {
10 #has_many :replied_messages, {
11 # :class_name => "Message",
11 # :class_name => "Message",
12 # :foreign_key => "replying_message_id"
12 # :foreign_key => "replying_message_id"
13 #}
13 #}
14 #
14 #
15
15
16 attr_accessor :replied_messages
16 attr_accessor :replied_messages
17
17
18 def self.find_all_sent_by_user(user)
18 def self.find_all_sent_by_user(user)
19 messages = user.messages
19 messages = user.messages
20 replied_messages = user.replied_messages
20 replied_messages = user.replied_messages
21 Message.build_replying_message_hierarchy messages, replied_messages
21 Message.build_replying_message_hierarchy messages, replied_messages
22 return messages
22 return messages
23 end
23 end
24 -
24 +
25 def self.find_all_system_unreplied_messages
25 def self.find_all_system_unreplied_messages
26 self.find(:all,
26 self.find(:all,
27 :conditions => 'ISNULL(receiver_id) ' +
27 :conditions => 'ISNULL(receiver_id) ' +
28 'AND (ISNULL(replied) OR replied=0)',
28 'AND (ISNULL(replied) OR replied=0)',
29 :order => 'created_at')
29 :order => 'created_at')
30 end
30 end
31
31
32 def self.build_replying_message_hierarchy(*args)
32 def self.build_replying_message_hierarchy(*args)
33 # manually build replies hierarchy (to improve efficiency)
33 # manually build replies hierarchy (to improve efficiency)
34 all_messages = {}
34 all_messages = {}
35
35
36 args.each do |collection|
36 args.each do |collection|
37 collection.each do |m|
37 collection.each do |m|
38 all_messages[m.id] = m
38 all_messages[m.id] = m
39 m.replied_messages = []
39 m.replied_messages = []
40 end
40 end
41 end
41 end
42
42
43 all_messages.each_value do |m|
43 all_messages.each_value do |m|
44 rep_id = m.replying_message_id
44 rep_id = m.replying_message_id
45 if all_messages[rep_id]!=nil
45 if all_messages[rep_id]!=nil
46 all_messages[rep_id].add_replied_message(m)
46 all_messages[rep_id].add_replied_message(m)
47 end
47 end
48 end
48 end
49 end
49 end
50
50
51 def add_replied_message(m)
51 def add_replied_message(m)
52 if @replied_messages==nil
52 if @replied_messages==nil
53 @replied_messages = [m]
53 @replied_messages = [m]
54 else
54 else
55 @replied_messages << m
55 @replied_messages << m
56 end
56 end
57 @replied_messages
57 @replied_messages
58 end
58 end
59
59
60 end
60 end
@@ -1,11 +1,12
1 %tr
1 %tr
2 - if short_message.sender
2 - if short_message.sender
3 %td=h short_message.sender.full_name
3 %td=h short_message.sender.full_name
4 - else
4 - else
5 %td (user deleted)
5 %td (user deleted)
6 %td= "#{short_message.created_at}"
6 %td= "#{short_message.created_at}"
7 %td=h truncate(short_message.body)
7 %td=h truncate(short_message.body)
8 %td
8 %td
9 - if short_message.sender
9 - if short_message.sender
10 = link_to "[reply]", :action => 'show', :id => short_message.id
10 = link_to "[reply]", :action => 'show', :id => short_message.id
11 - = link_to "[hide]", :action => 'hide', :id => short_message.id
11 + - if params[:action] != 'list_all'
12 + = link_to "[hide]", :action => 'hide', :id => short_message.id
@@ -1,43 +1,85
1 - content_for :head do
1 - content_for :head do
2 = stylesheet_link_tag 'problems'
2 = stylesheet_link_tag 'problems'
3 + = javascript_include_tag 'local_jquery'
4 +
5 + :javascript
6 + $(document).ready( function() {
7 + function shiftclick(start,stop,value) {
8 + $('tr input').each( function(id,input) {
9 + var $input=$(input);
10 + var iid=parseInt($input.attr('id').split('-')[2]);
11 + if(iid>=start&&iid<=stop){
12 + $input.prop('checked',value)
13 + }
14 + });
15 + }
16 +
17 + $('tr input').click( function(e) {
18 + if (e.shiftKey) {
19 + stop = parseInt($(this).attr('id').split('-')[2]);
20 + var orig_stop = stop
21 + if (typeof start !== 'undefined') {
22 + if (start > stop) {
23 + var tmp = start;
24 + start = stop;
25 + stop = tmp;
26 + }
27 + shiftclick(start,stop,$(this).is(':checked') )
28 + }
29 + start = orig_stop
30 + } else {
31 + start = parseInt($(this).attr('id').split('-')[2]);
32 + }
33 + });
34 + });
35 +
3
36
4 %h1 Manage problems
37 %h1 Manage problems
5
38
6 %p= link_to '[Back to problem list]', :action => 'list'
39 %p= link_to '[Back to problem list]', :action => 'list'
7
40
8 = form_tag :action=>'do_manage' do
41 = form_tag :action=>'do_manage' do
9 .submitbox
42 .submitbox
10 - What do you want to do?
43 + What do you want to do to the selected problem?
11 %br/
44 %br/
45 + (You can shift-click to select a range of problems)
12 %ul
46 %ul
13 %li
47 %li
14 Change date added to
48 Change date added to
15 = select_date Date.current, :prefix => 'date_added'
49 = select_date Date.current, :prefix => 'date_added'
16 &nbsp;&nbsp;&nbsp;
50 &nbsp;&nbsp;&nbsp;
17 = submit_tag 'Change', :name => 'change_date_added'
51 = submit_tag 'Change', :name => 'change_date_added'
52 + %li
53 + Set available to
54 + = submit_tag 'True', :name => 'enable_problem'
55 + = submit_tag 'False', :name => 'disable_problem'
18
56
19 - if GraderConfiguration.multicontests?
57 - if GraderConfiguration.multicontests?
20 %li
58 %li
21 Add to
59 Add to
22 = select("contest","id",Contest.all.collect {|c| [c.title, c.id]})
60 = select("contest","id",Contest.all.collect {|c| [c.title, c.id]})
23 = submit_tag 'Add', :name => 'add_to_contest'
61 = submit_tag 'Add', :name => 'add_to_contest'
24
62
25 %table
63 %table
26 - %tr
64 + %tr{style: "text-align: left;"}
27 - %th/
65 + %th= check_box_tag 'select_all'
28 %th Name
66 %th Name
29 %th Full name
67 %th Full name
68 + %th Available
30 %th Date added
69 %th Date added
31 - if GraderConfiguration.multicontests?
70 - if GraderConfiguration.multicontests?
32 %th Contests
71 %th Contests
33
72
73 + - num = 0
34 - for problem in @problems
74 - for problem in @problems
75 + - num += 1
35 %tr{:id => "row-prob-#{problem.id}", :name=> "prob-#{problem.id}"}
76 %tr{:id => "row-prob-#{problem.id}", :name=> "prob-#{problem.id}"}
36 - %td= check_box_tag "prob-#{problem.id}"
77 + %td= check_box_tag "prob-#{problem.id}-#{num}"
37 %td= problem.name
78 %td= problem.name
38 %td= problem.full_name
79 %td= problem.full_name
80 + %td= problem.available
39 %td= problem.date_added
81 %td= problem.date_added
40 - if GraderConfiguration.multicontests?
82 - if GraderConfiguration.multicontests?
41 %td
83 %td
42 - problem.contests.each do |contest|
84 - problem.contests.each do |contest|
43 = "(#{contest.name} [#{link_to 'x', :action => 'remove_contest', :id => problem.id, :contest_id => contest.id }])"
85 = "(#{contest.name} [#{link_to 'x', :action => 'remove_contest', :id => problem.id, :contest_id => contest.id }])"
@@ -1,36 +1,36
1 - content_for :header do
1 - content_for :header do
2 = stylesheet_link_tag 'tablesorter-theme.cafe'
2 = stylesheet_link_tag 'tablesorter-theme.cafe'
3 - = javascript_include_tag 'new'
3 + = javascript_include_tag 'local_jquery'
4
4
5 %script{:type=>"text/javascript"}
5 %script{:type=>"text/javascript"}
6 $(function () {
6 $(function () {
7 $('#since_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
7 $('#since_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
8 $('#until_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
8 $('#until_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
9 $('#my_table').tablesorter({widthFixed: true, widgets: ['zebra']});
9 $('#my_table').tablesorter({widthFixed: true, widgets: ['zebra']});
10 });
10 });
11
11
12 %h1 Login status
12 %h1 Login status
13
13
14 =render partial: 'report_menu'
14 =render partial: 'report_menu'
15 =render partial: 'date_range', locals: {param_text: 'Login date range:', title: 'Query login stat in the range' }
15 =render partial: 'date_range', locals: {param_text: 'Login date range:', title: 'Query login stat in the range' }
16
16
17 %table.tablesorter-cafe#my_table
17 %table.tablesorter-cafe#my_table
18 %thead
18 %thead
19 %tr
19 %tr
20 %th login
20 %th login
21 %th full name
21 %th full name
22 %th login count
22 %th login count
23 %th earliest
23 %th earliest
24 %th latest
24 %th latest
25 %th IP
25 %th IP
26 %tbody
26 %tbody
27 - @logins.each do |l|
27 - @logins.each do |l|
28 %tr{class: cycle('info-even','info-odd')}
28 %tr{class: cycle('info-even','info-odd')}
29 %td= link_to l[:login], controller: 'users', action: 'profile', id: l[:id]
29 %td= link_to l[:login], controller: 'users', action: 'profile', id: l[:id]
30 %td= l[:full_name]
30 %td= l[:full_name]
31 %td= l[:count]
31 %td= l[:count]
32 %td= l[:min] ? l[:min].in_time_zone.strftime('%Y-%m-%d %H:%M') : ''
32 %td= l[:min] ? l[:min].in_time_zone.strftime('%Y-%m-%d %H:%M') : ''
33 %td= l[:max] ? "#{l[:max].in_time_zone.strftime('%Y-%m-%d %H:%M.%S')} (#{time_ago_in_words(l[:max].in_time_zone)} ago)" : ''
33 %td= l[:max] ? "#{l[:max].in_time_zone.strftime('%Y-%m-%d %H:%M.%S')} (#{time_ago_in_words(l[:max].in_time_zone)} ago)" : ''
34 %td
34 %td
35 - l[:ip].each do |ip|
35 - l[:ip].each do |ip|
36 #{ip.ip_address} <br/>
36 #{ip.ip_address} <br/>
@@ -1,37 +1,37
1 - content_for :header do
1 - content_for :header do
2 - = javascript_include_tag 'new'
2 + = javascript_include_tag 'local_jquery'
3
3
4 %script{:type=>"text/javascript"}
4 %script{:type=>"text/javascript"}
5 $(function () {
5 $(function () {
6 $('#since_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
6 $('#since_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
7 $('#until_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
7 $('#until_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
8 });
8 });
9
9
10 %h1 Login status
10 %h1 Login status
11
11
12 =render partial: 'report_menu'
12 =render partial: 'report_menu'
13 =render partial: 'date_range', locals: {param_text: 'Submission date range:', title: 'Query submission stat in the range' }
13 =render partial: 'date_range', locals: {param_text: 'Submission date range:', title: 'Query submission stat in the range' }
14
14
15 %table.info
15 %table.info
16 %thead
16 %thead
17 %tr.info-head
17 %tr.info-head
18 %th login
18 %th login
19 %th full name
19 %th full name
20 %th total submissions
20 %th total submissions
21 %th submissions
21 %th submissions
22 %tbody
22 %tbody
23 - @submissions.each do |user_id,data|
23 - @submissions.each do |user_id,data|
24 %tr{class: cycle('info-even','info-odd')}
24 %tr{class: cycle('info-even','info-odd')}
25 %td= data[:login]
25 %td= data[:login]
26 %td= data[:full_name]
26 %td= data[:full_name]
27 %td= data[:count]
27 %td= data[:count]
28 %td
28 %td
29 - data[:sub].each do |prob_id,sub_data|
29 - data[:sub].each do |prob_id,sub_data|
30 = "#{sub_data[:prob_name]}: ["
30 = "#{sub_data[:prob_name]}: ["
31 - st = []
31 - st = []
32 - sub_data[:sub_ids].each do |id|
32 - sub_data[:sub_ids].each do |id|
33 - st << link_to(id, controller: 'graders' , action: 'submission', id: id)
33 - st << link_to(id, controller: 'graders' , action: 'submission', id: id)
34 = raw st.join ', '
34 = raw st.join ', '
35 = ']'
35 = ']'
36 %br/
36 %br/
37
37
@@ -1,59 +1,59
1 - content_for :header do
1 - content_for :header do
2 - = javascript_include_tag 'new'
2 + = javascript_include_tag 'local_jquery'
3 = stylesheet_link_tag 'tablesorter-theme.cafe'
3 = stylesheet_link_tag 'tablesorter-theme.cafe'
4
4
5 %script{:type=>"text/javascript"}
5 %script{:type=>"text/javascript"}
6 $(function () {
6 $(function () {
7 $('#since_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
7 $('#since_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
8 $('#until_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
8 $('#until_datetime').datetimepicker({ showButtonPanel: true, dateFormat: "yy-mm-dd", controlType: "slider"} );
9 $('#my_table').tablesorter({widgets: ['zebra']});
9 $('#my_table').tablesorter({widgets: ['zebra']});
10 });
10 });
11
11
12 %h1 User grading results
12 %h1 User grading results
13 %h2= params[:action] == 'user_stat' ? "Show scores from latest submission" : "Show max scores in submission range"
13 %h2= params[:action] == 'user_stat' ? "Show scores from latest submission" : "Show max scores in submission range"
14
14
15
15
16 - if @problem and @problem.errors
16 - if @problem and @problem.errors
17 =error_messages_for 'problem'
17 =error_messages_for 'problem'
18
18
19 = render partial: 'submission_range'
19 = render partial: 'submission_range'
20
20
21 - if params[:action] == 'user_stat'
21 - if params[:action] == 'user_stat'
22 %h3 Latest score
22 %h3 Latest score
23 = link_to '[download csv with all problems]', controller: :user_admin, action: :user_stat, commit: 'download csv'
23 = link_to '[download csv with all problems]', controller: :user_admin, action: :user_stat, commit: 'download csv'
24 - else
24 - else
25 %h3 Max score
25 %h3 Max score
26 = link_to '[Show only latest submissions]', controller: :user_admin, action: :user_stat
26 = link_to '[Show only latest submissions]', controller: :user_admin, action: :user_stat
27 = link_to '[download csv with all problems]', controller: :user_admin, action: :user_stat_max, commit: 'download csv'
27 = link_to '[download csv with all problems]', controller: :user_admin, action: :user_stat_max, commit: 'download csv'
28
28
29 %table.tablesorter-cafe#my_table
29 %table.tablesorter-cafe#my_table
30 %thead
30 %thead
31 %tr
31 %tr
32 %th User
32 %th User
33 %th Name
33 %th Name
34 %th Activated?
34 %th Activated?
35 %th Logged in
35 %th Logged in
36 %th Contest(s)
36 %th Contest(s)
37 %th Section
37 %th Section
38 - @problems.each do |p|
38 - @problems.each do |p|
39 %th= p.name
39 %th= p.name
40 %th Total
40 %th Total
41 %th Passed
41 %th Passed
42 %tbody
42 %tbody
43 - @scorearray.each do |sc|
43 - @scorearray.each do |sc|
44 %tr{class: cycle('info-even','info-odd')}
44 %tr{class: cycle('info-even','info-odd')}
45 - total,num_passed = 0,0
45 - total,num_passed = 0,0
46 - sc.each_index do |i|
46 - sc.each_index do |i|
47 - if i == 0
47 - if i == 0
48 %td= link_to sc[i].login, controller: 'users', action: 'profile', id: sc[i]
48 %td= link_to sc[i].login, controller: 'users', action: 'profile', id: sc[i]
49 %td= sc[i].full_name
49 %td= sc[i].full_name
50 %td= sc[i].activated
50 %td= sc[i].activated
51 %td= sc[i].try(:contest_stat).try(:started_at)!=nil ? 'yes' : 'no'
51 %td= sc[i].try(:contest_stat).try(:started_at)!=nil ? 'yes' : 'no'
52 %td= sc[i].contests.collect {|c| c.name}.join(', ')
52 %td= sc[i].contests.collect {|c| c.name}.join(', ')
53 %td= sc[i].section
53 %td= sc[i].section
54 - else
54 - else
55 %td= sc[i][0]
55 %td= sc[i][0]
56 - total += sc[i][0]
56 - total += sc[i][0]
57 - num_passed += 1 if sc[i][1]
57 - num_passed += 1 if sc[i][1]
58 %td= total
58 %td= total
59 %td= num_passed
59 %td= num_passed
@@ -1,52 +1,52
1 - content_for :header do
1 - content_for :header do
2 - = javascript_include_tag 'new'
2 + = javascript_include_tag 'local_jquery'
3
3
4 %script{:type=>"text/javascript"}
4 %script{:type=>"text/javascript"}
5 $(function () {
5 $(function () {
6 $('#submission_table').tablesorter({widgets: ['zebra']});
6 $('#submission_table').tablesorter({widgets: ['zebra']});
7 });
7 });
8
8
9 :css
9 :css
10 .fix-width {
10 .fix-width {
11 font-family: Droid Sans Mono,Consolas, monospace, mono, Courier New, Courier;
11 font-family: Droid Sans Mono,Consolas, monospace, mono, Courier New, Courier;
12 }
12 }
13
13
14 %h1= @user.full_name + ' Profile'
14 %h1= @user.full_name + ' Profile'
15
15
16 %h2 Basic info
16 %h2 Basic info
17 <b>Login:</b> #{@user.login} <br/>
17 <b>Login:</b> #{@user.login} <br/>
18 <b>Full name:</b> #{@user.full_name} <br />
18 <b>Full name:</b> #{@user.full_name} <br />
19
19
20
20
21 %h2 Problem Stat
21 %h2 Problem Stat
22
22
23 %h2 Submissions
23 %h2 Submissions
24
24
25 %table.tablesorter-cafe#submission_table
25 %table.tablesorter-cafe#submission_table
26 %thead
26 %thead
27 %tr
27 %tr
28 %th ID
28 %th ID
29 %th Problem code
29 %th Problem code
30 %th Problem full name
30 %th Problem full name
31 %th Language
31 %th Language
32 %th Submitted at
32 %th Submitted at
33 %th Result
33 %th Result
34 %th Score
34 %th Score
35 - if session[:admin]
35 - if session[:admin]
36 %th IP
36 %th IP
37 %tbody
37 %tbody
38 - @submission.each do |s|
38 - @submission.each do |s|
39 - next unless s.problem
39 - next unless s.problem
40 %tr
40 %tr
41 %td= link_to "#{s.id}", controller: "graders", action: "submission", id: s.id
41 %td= link_to "#{s.id}", controller: "graders", action: "submission", id: s.id
42 %td= s.problem.name
42 %td= s.problem.name
43 %td= s.problem.full_name
43 %td= s.problem.full_name
44 %td= s.language.pretty_name
44 %td= s.language.pretty_name
45 %td #{s.submitted_at.strftime('%Y-%m-%d %H:%M')} (#{time_ago_in_words(s.submitted_at)} ago)
45 %td #{s.submitted_at.strftime('%Y-%m-%d %H:%M')} (#{time_ago_in_words(s.submitted_at)} ago)
46 %td.fix-width= s.grader_comment
46 %td.fix-width= s.grader_comment
47 %td= (s.points*100)/s.problem.full_score
47 %td= (s.points*100)/s.problem.full_score
48 - if session[:admin]
48 - if session[:admin]
49 %td= s.ip_address
49 %td= s.ip_address
50
50
51
51
52
52
@@ -1,65 +1,65
1 require File.expand_path('../boot', __FILE__)
1 require File.expand_path('../boot', __FILE__)
2
2
3 require 'rails/all'
3 require 'rails/all'
4
4
5 if defined?(Bundler)
5 if defined?(Bundler)
6 # If you precompile assets before deploying to production, use this line
6 # If you precompile assets before deploying to production, use this line
7 Bundler.require(*Rails.groups(:assets => %w(development test)))
7 Bundler.require(*Rails.groups(:assets => %w(development test)))
8 # If you want your assets lazily compiled in production, use this line
8 # If you want your assets lazily compiled in production, use this line
9 # Bundler.require(:default, :assets, Rails.env)
9 # Bundler.require(:default, :assets, Rails.env)
10 end
10 end
11
11
12 module CafeGrader
12 module CafeGrader
13 class Application < Rails::Application
13 class Application < Rails::Application
14 # Settings in config/environments/* take precedence over those specified here.
14 # Settings in config/environments/* take precedence over those specified here.
15 # Application configuration should go into files in config/initializers
15 # Application configuration should go into files in config/initializers
16 # -- all .rb files in that directory are automatically loaded.
16 # -- all .rb files in that directory are automatically loaded.
17
17
18 # Custom directories with classes and modules you want to be autoloadable.
18 # Custom directories with classes and modules you want to be autoloadable.
19 config.autoload_paths += %W(#{config.root}/lib)
19 config.autoload_paths += %W(#{config.root}/lib)
20
20
21 # Only load the plugins named here, in the order given (default is alphabetical).
21 # Only load the plugins named here, in the order given (default is alphabetical).
22 # :all can be used as a placeholder for all plugins not explicitly named.
22 # :all can be used as a placeholder for all plugins not explicitly named.
23 # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
23 # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
24
24
25 # Activate observers that should always be running.
25 # Activate observers that should always be running.
26 # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
26 # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
27
27
28 # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
28 # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
29 # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
29 # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
30 config.time_zone = 'UTC'
30 config.time_zone = 'UTC'
31
31
32 # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
32 # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
33 # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
33 # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
34 config.i18n.default_locale = :en
34 config.i18n.default_locale = :en
35
35
36 # Configure the default encoding used in templates for Ruby 1.9.
36 # Configure the default encoding used in templates for Ruby 1.9.
37 config.encoding = "utf-8"
37 config.encoding = "utf-8"
38
38
39 # Configure sensitive parameters which will be filtered from the log file.
39 # Configure sensitive parameters which will be filtered from the log file.
40 config.filter_parameters += [:password]
40 config.filter_parameters += [:password]
41
41
42 # Enable escaping HTML in JSON.
42 # Enable escaping HTML in JSON.
43 config.active_support.escape_html_entities_in_json = true
43 config.active_support.escape_html_entities_in_json = true
44
44
45 # Use SQL instead of Active Record's schema dumper when creating the database.
45 # Use SQL instead of Active Record's schema dumper when creating the database.
46 # This is necessary if your schema can't be completely dumped by the schema dumper,
46 # This is necessary if your schema can't be completely dumped by the schema dumper,
47 # like if you have constraints or database-specific column types
47 # like if you have constraints or database-specific column types
48 # config.active_record.schema_format = :sql
48 # config.active_record.schema_format = :sql
49
49
50 # Enforce whitelist mode for mass assignment.
50 # Enforce whitelist mode for mass assignment.
51 # This will create an empty whitelist of attributes available for mass-assignment for all models
51 # This will create an empty whitelist of attributes available for mass-assignment for all models
52 # in your app. As such, your models will need to explicitly whitelist or blacklist accessible
52 # in your app. As such, your models will need to explicitly whitelist or blacklist accessible
53 # parameters by using an attr_accessible or attr_protected declaration.
53 # parameters by using an attr_accessible or attr_protected declaration.
54 config.active_record.whitelist_attributes = false
54 config.active_record.whitelist_attributes = false
55
55
56 # Enable the asset pipeline
56 # Enable the asset pipeline
57 config.assets.enabled = true
57 config.assets.enabled = true
58
58
59 # Version of your assets, change this if you want to expire all your assets
59 # Version of your assets, change this if you want to expire all your assets
60 config.assets.version = '1.0'
60 config.assets.version = '1.0'
61
61
62 config.assets.precompile += ['announcement_refresh.js','effects.js','site_update.js','graders.css','problems.css']
62 config.assets.precompile += ['announcement_refresh.js','effects.js','site_update.js','graders.css','problems.css']
63 - config.assets.precompile += ['new.js','tablesorter-theme.cafe.css']
63 + config.assets.precompile += ['local_jquery.js','tablesorter-theme.cafe.css']
64 end
64 end
65 end
65 end
deleted file
You need to be logged in to leave comments. Login now