Description:
merge
Commit status:
[Not Reviewed]
References:
Diff options:
Comments:
0 Commit comments
0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
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,72 +1,77 | |||||
|
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| |
@@ -119,130 +119,142 | |||||
|
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 |
- els |
|
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 | |
|
50 | |
|
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 ' |
|
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 ' |
|
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,50 +1,50 | |||||
|
1 | - content_for :header do |
|
1 | - content_for :header do |
|
2 |
- = javascript_include_tag ' |
|
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 |
@@ -1,50 +1,50 | |||||
|
1 | - content_for :header do |
|
1 | - content_for :header do |
|
2 |
- = javascript_include_tag ' |
|
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 |
@@ -15,51 +15,51 | |||||
|
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 += [' |
|
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