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

r795:08d968fa05d5 - - 11 files changed: 54 inserted, 17 deleted

@@ -0,0 +1,8
1 + = render partial: 'toggle_button',
2 + locals: {button_id: "#group-enabled-#{@group.id}",button_on: @group.enabled }
3 + :plain
4 + r = $("#group-#{@group.id}");
5 + r.removeClass('success');
6 + r.removeClass('danger');
7 + r.addClass("#{@group.enabled? ? 'success' : 'danger'}");
8 +
@@ -0,0 +1,5
1 + class AddEnabledToGroup < ActiveRecord::Migration[5.2]
2 + def change
3 + add_column :groups, :enabled, :boolean, default: true
4 + end
5 + end
@@ -1,104 +1,110
1 class GroupsController < ApplicationController
1 class GroupsController < ApplicationController
2 before_action :set_group, only: [:show, :edit, :update, :destroy,
2 before_action :set_group, only: [:show, :edit, :update, :destroy,
3 :add_user, :remove_user,:remove_all_user,
3 :add_user, :remove_user,:remove_all_user,
4 :add_problem, :remove_problem,:remove_all_problem,
4 :add_problem, :remove_problem,:remove_all_problem,
5 + :toggle,
5 ]
6 ]
6 before_action :admin_authorization
7 before_action :admin_authorization
7
8
8 # GET /groups
9 # GET /groups
9 def index
10 def index
10 @groups = Group.all
11 @groups = Group.all
11 end
12 end
12
13
13 # GET /groups/1
14 # GET /groups/1
14 def show
15 def show
15 end
16 end
16
17
17 # GET /groups/new
18 # GET /groups/new
18 def new
19 def new
19 @group = Group.new
20 @group = Group.new
20 end
21 end
21
22
22 # GET /groups/1/edit
23 # GET /groups/1/edit
23 def edit
24 def edit
24 end
25 end
25
26
26 # POST /groups
27 # POST /groups
27 def create
28 def create
28 @group = Group.new(group_params)
29 @group = Group.new(group_params)
29
30
30 if @group.save
31 if @group.save
31 redirect_to @group, notice: 'Group was successfully created.'
32 redirect_to @group, notice: 'Group was successfully created.'
32 else
33 else
33 render :new
34 render :new
34 end
35 end
35 end
36 end
36
37
37 # PATCH/PUT /groups/1
38 # PATCH/PUT /groups/1
38 def update
39 def update
39 if @group.update(group_params)
40 if @group.update(group_params)
40 redirect_to @group, notice: 'Group was successfully updated.'
41 redirect_to @group, notice: 'Group was successfully updated.'
41 else
42 else
42 render :edit
43 render :edit
43 end
44 end
44 end
45 end
45
46
46 # DELETE /groups/1
47 # DELETE /groups/1
47 def destroy
48 def destroy
48 @group.destroy
49 @group.destroy
49 redirect_to groups_url, notice: 'Group was successfully destroyed.'
50 redirect_to groups_url, notice: 'Group was successfully destroyed.'
50 end
51 end
51
52
53 + def toggle
54 + @group.enabled = @group.enabled? ? false : true
55 + @group.save
56 + end
57 +
52 def remove_user
58 def remove_user
53 user = User.find(params[:user_id])
59 user = User.find(params[:user_id])
54 @group.users.delete(user)
60 @group.users.delete(user)
55 redirect_to group_path(@group), flash: {success: "User #{user.login} was removed from the group #{@group.name}"}
61 redirect_to group_path(@group), flash: {success: "User #{user.login} was removed from the group #{@group.name}"}
56 end
62 end
57
63
58 def remove_all_user
64 def remove_all_user
59 @group.users.clear
65 @group.users.clear
60 redirect_to group_path(@group), alert: 'All users removed'
66 redirect_to group_path(@group), alert: 'All users removed'
61 end
67 end
62
68
63 def remove_all_problem
69 def remove_all_problem
64 @group.problems.clear
70 @group.problems.clear
65 redirect_to group_path(@group), alert: 'All problems removed'
71 redirect_to group_path(@group), alert: 'All problems removed'
66 end
72 end
67
73
68 def add_user
74 def add_user
69 user = User.find(params[:user_id])
75 user = User.find(params[:user_id])
70 begin
76 begin
71 @group.users << user
77 @group.users << user
72 redirect_to group_path(@group), flash: { success: "User #{user.login} was add to the group #{@group.name}"}
78 redirect_to group_path(@group), flash: { success: "User #{user.login} was add to the group #{@group.name}"}
73 rescue => e
79 rescue => e
74 redirect_to group_path(@group), alert: e.message
80 redirect_to group_path(@group), alert: e.message
75 end
81 end
76 end
82 end
77
83
78 def remove_problem
84 def remove_problem
79 problem = Problem.find(params[:problem_id])
85 problem = Problem.find(params[:problem_id])
80 @group.problems.delete(problem)
86 @group.problems.delete(problem)
81 redirect_to group_path(@group), flash: {success: "Problem #{problem.name} was removed from the group #{@group.name}" }
87 redirect_to group_path(@group), flash: {success: "Problem #{problem.name} was removed from the group #{@group.name}" }
82 end
88 end
83
89
84 def add_problem
90 def add_problem
85 problem = Problem.find(params[:problem_id])
91 problem = Problem.find(params[:problem_id])
86 begin
92 begin
87 @group.problems << problem
93 @group.problems << problem
88 redirect_to group_path(@group), flash: {success: "Problem #{problem.name} was add to the group #{@group.name}" }
94 redirect_to group_path(@group), flash: {success: "Problem #{problem.name} was add to the group #{@group.name}" }
89 rescue => e
95 rescue => e
90 redirect_to group_path(@group), alert: e.message
96 redirect_to group_path(@group), alert: e.message
91 end
97 end
92 end
98 end
93
99
94 private
100 private
95 # Use callbacks to share common setup or constraints between actions.
101 # Use callbacks to share common setup or constraints between actions.
96 def set_group
102 def set_group
97 @group = Group.find(params[:id])
103 @group = Group.find(params[:id])
98 end
104 end
99
105
100 # Only allow a trusted parameter "white list" through.
106 # Only allow a trusted parameter "white list" through.
101 def group_params
107 def group_params
102 - params.require(:group).permit(:name, :description)
108 + params.require(:group).permit(:name, :description, :enabled)
103 end
109 end
104 end
110 end
@@ -143,97 +143,97
143 case_num = params[:num].to_i
143 case_num = params[:num].to_i
144 out_filename = output_filename(@user.login,
144 out_filename = output_filename(@user.login,
145 @submission.problem.name,
145 @submission.problem.name,
146 @submission.id,
146 @submission.id,
147 case_num)
147 case_num)
148 if !FileTest.exists?(out_filename)
148 if !FileTest.exists?(out_filename)
149 flash[:notice] = 'Output not found.'
149 flash[:notice] = 'Output not found.'
150 redirect_to :action => 'list' and return
150 redirect_to :action => 'list' and return
151 end
151 end
152
152
153 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
153 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
154 response.headers['Content-Type'] = "application/force-download"
154 response.headers['Content-Type'] = "application/force-download"
155 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
155 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
156 response.headers["X-Sendfile"] = out_filename
156 response.headers["X-Sendfile"] = out_filename
157 response.headers['Content-length'] = File.size(out_filename)
157 response.headers['Content-length'] = File.size(out_filename)
158 render :nothing => true
158 render :nothing => true
159 else
159 else
160 send_file out_filename, :stream => false, :filename => "output-#{case_num}.txt", :type => "text/plain"
160 send_file out_filename, :stream => false, :filename => "output-#{case_num}.txt", :type => "text/plain"
161 end
161 end
162 end
162 end
163
163
164 def error
164 def error
165 @user = User.find(session[:user_id])
165 @user = User.find(session[:user_id])
166 end
166 end
167
167
168 # announcement refreshing and hiding methods
168 # announcement refreshing and hiding methods
169
169
170 def announcements
170 def announcements
171 if params.has_key? 'recent'
171 if params.has_key? 'recent'
172 prepare_announcements(params[:recent])
172 prepare_announcements(params[:recent])
173 else
173 else
174 prepare_announcements
174 prepare_announcements
175 end
175 end
176 render(:partial => 'announcement',
176 render(:partial => 'announcement',
177 :collection => @announcements,
177 :collection => @announcements,
178 :locals => {:announcement_effect => true})
178 :locals => {:announcement_effect => true})
179 end
179 end
180
180
181 def confirm_contest_start
181 def confirm_contest_start
182 user = User.find(session[:user_id])
182 user = User.find(session[:user_id])
183 if request.method == 'POST'
183 if request.method == 'POST'
184 user.update_start_time
184 user.update_start_time
185 redirect_to :action => 'list'
185 redirect_to :action => 'list'
186 else
186 else
187 @contests = user.contests
187 @contests = user.contests
188 @user = user
188 @user = user
189 end
189 end
190 end
190 end
191 -
191 +
192 protected
192 protected
193
193
194 def prepare_announcements(recent=nil)
194 def prepare_announcements(recent=nil)
195 if GraderConfiguration.show_tasks_to?(@user)
195 if GraderConfiguration.show_tasks_to?(@user)
196 @announcements = Announcement.published(true)
196 @announcements = Announcement.published(true)
197 else
197 else
198 @announcements = Announcement.published
198 @announcements = Announcement.published
199 end
199 end
200 if recent!=nil
200 if recent!=nil
201 recent_id = recent.to_i
201 recent_id = recent.to_i
202 @announcements = @announcements.find_all { |a| a.id > recent_id }
202 @announcements = @announcements.find_all { |a| a.id > recent_id }
203 end
203 end
204 end
204 end
205
205
206 def prepare_list_information
206 def prepare_list_information
207 @user = User.find(session[:user_id])
207 @user = User.find(session[:user_id])
208 if not GraderConfiguration.multicontests?
208 if not GraderConfiguration.multicontests?
209 @problems = @user.available_problems
209 @problems = @user.available_problems
210 else
210 else
211 @contest_problems = @user.available_problems_group_by_contests
211 @contest_problems = @user.available_problems_group_by_contests
212 @problems = @user.available_problems
212 @problems = @user.available_problems
213 end
213 end
214 @prob_submissions = {}
214 @prob_submissions = {}
215 @problems.each do |p|
215 @problems.each do |p|
216 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
216 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
217 if sub!=nil
217 if sub!=nil
218 @prob_submissions[p.id] = { :count => sub.number, :submission => sub }
218 @prob_submissions[p.id] = { :count => sub.number, :submission => sub }
219 else
219 else
220 @prob_submissions[p.id] = { :count => 0, :submission => nil }
220 @prob_submissions[p.id] = { :count => 0, :submission => nil }
221 end
221 end
222 end
222 end
223 prepare_announcements
223 prepare_announcements
224 end
224 end
225
225
226 def check_viewability
226 def check_viewability
227 @user = User.find(session[:user_id])
227 @user = User.find(session[:user_id])
228 if (!GraderConfiguration.show_tasks_to?(@user)) and
228 if (!GraderConfiguration.show_tasks_to?(@user)) and
229 ((action_name=='submission') or (action_name=='submit'))
229 ((action_name=='submission') or (action_name=='submit'))
230 redirect_to :action => 'list' and return
230 redirect_to :action => 'list' and return
231 end
231 end
232 end
232 end
233
233
234 def prepare_grading_result(submission)
234 def prepare_grading_result(submission)
235 if GraderConfiguration.task_grading_info.has_key? submission.problem.name
235 if GraderConfiguration.task_grading_info.has_key? submission.problem.name
236 grading_info = GraderConfiguration.task_grading_info[submission.problem.name]
236 grading_info = GraderConfiguration.task_grading_info[submission.problem.name]
237 else
237 else
238 # guess task info from problem.full_score
238 # guess task info from problem.full_score
239 cases = submission.problem.full_score / 10
239 cases = submission.problem.full_score / 10
@@ -68,98 +68,99
68 append_to menu_items, "[#{I18n.t 'menu.hall_of_fame'}]", 'report', 'problem_hof'
68 append_to menu_items, "[#{I18n.t 'menu.hall_of_fame'}]", 'report', 'problem_hof'
69 end
69 end
70 append_to menu_items, "[#{I18n.t 'menu.help'}]", 'main', 'help'
70 append_to menu_items, "[#{I18n.t 'menu.help'}]", 'main', 'help'
71
71
72 if GraderConfiguration['system.user_setting_enabled']
72 if GraderConfiguration['system.user_setting_enabled']
73 append_to menu_items, "[#{I18n.t 'menu.settings'}]", 'users', 'index'
73 append_to menu_items, "[#{I18n.t 'menu.settings'}]", 'users', 'index'
74 end
74 end
75 append_to menu_items, "[#{I18n.t 'menu.log_out'}]", 'main', 'login'
75 append_to menu_items, "[#{I18n.t 'menu.log_out'}]", 'main', 'login'
76
76
77 menu_items.html_safe
77 menu_items.html_safe
78 end
78 end
79
79
80 def append_to(option,label, controller, action)
80 def append_to(option,label, controller, action)
81 option << ' ' if option!=''
81 option << ' ' if option!=''
82 option << link_to_unless_current(label,
82 option << link_to_unless_current(label,
83 :controller => controller,
83 :controller => controller,
84 :action => action)
84 :action => action)
85 end
85 end
86
86
87 def format_short_time(time)
87 def format_short_time(time)
88 now = Time.zone.now
88 now = Time.zone.now
89 st = ''
89 st = ''
90 if (time.yday != now.yday) or (time.year != now.year)
90 if (time.yday != now.yday) or (time.year != now.year)
91 st = time.strftime("%d/%m/%y ")
91 st = time.strftime("%d/%m/%y ")
92 end
92 end
93 st + time.strftime("%X")
93 st + time.strftime("%X")
94 end
94 end
95
95
96 def format_short_duration(duration)
96 def format_short_duration(duration)
97 return '' if duration==nil
97 return '' if duration==nil
98 d = duration.to_f
98 d = duration.to_f
99 return Time.at(d).gmtime.strftime("%X")
99 return Time.at(d).gmtime.strftime("%X")
100 end
100 end
101
101
102 def format_full_time_ago(time)
102 def format_full_time_ago(time)
103 st = time_ago_in_words(time) + ' ago (' + format_short_time(time) + ')'
103 st = time_ago_in_words(time) + ' ago (' + format_short_time(time) + ')'
104 end
104 end
105
105
106 def read_textfile(fname,max_size=2048)
106 def read_textfile(fname,max_size=2048)
107 begin
107 begin
108 File.open(fname).read(max_size)
108 File.open(fname).read(max_size)
109 rescue
109 rescue
110 nil
110 nil
111 end
111 end
112 end
112 end
113
113
114 def toggle_button(on,toggle_url,id, option={})
114 def toggle_button(on,toggle_url,id, option={})
115 btn_size = option[:size] || 'btn-xs'
115 btn_size = option[:size] || 'btn-xs'
116 + btn_block = option[:block] || 'btn-block'
116 link_to (on ? "Yes" : "No"), toggle_url,
117 link_to (on ? "Yes" : "No"), toggle_url,
117 - {class: "btn btn-block #{btn_size} btn-#{on ? 'success' : 'default'} ajax-toggle",
118 + {class: "btn #{btn_block} #{btn_size} btn-#{on ? 'success' : 'default'} ajax-toggle",
118 id: id,
119 id: id,
119 data: {remote: true, method: 'get'}}
120 data: {remote: true, method: 'get'}}
120 end
121 end
121
122
122 def get_ace_mode(language)
123 def get_ace_mode(language)
123 # return ace mode string from Language
124 # return ace mode string from Language
124
125
125 case language.pretty_name
126 case language.pretty_name
126 when 'Pascal'
127 when 'Pascal'
127 'ace/mode/pascal'
128 'ace/mode/pascal'
128 when 'C++','C'
129 when 'C++','C'
129 'ace/mode/c_cpp'
130 'ace/mode/c_cpp'
130 when 'Ruby'
131 when 'Ruby'
131 'ace/mode/ruby'
132 'ace/mode/ruby'
132 when 'Python'
133 when 'Python'
133 'ace/mode/python'
134 'ace/mode/python'
134 when 'Java'
135 when 'Java'
135 'ace/mode/java'
136 'ace/mode/java'
136 else
137 else
137 'ace/mode/c_cpp'
138 'ace/mode/c_cpp'
138 end
139 end
139 end
140 end
140
141
141
142
142 def user_title_bar(user)
143 def user_title_bar(user)
143 header = ''
144 header = ''
144 time_left = ''
145 time_left = ''
145
146
146 #
147 #
147 # if the contest is over
148 # if the contest is over
148 if GraderConfiguration.time_limit_mode?
149 if GraderConfiguration.time_limit_mode?
149 if user.contest_finished?
150 if user.contest_finished?
150 header = <<CONTEST_OVER
151 header = <<CONTEST_OVER
151 <tr><td colspan="2" align="center">
152 <tr><td colspan="2" align="center">
152 <span class="contest-over-msg">THE CONTEST IS OVER</span>
153 <span class="contest-over-msg">THE CONTEST IS OVER</span>
153 </td></tr>
154 </td></tr>
154 CONTEST_OVER
155 CONTEST_OVER
155 end
156 end
156 if !user.contest_started?
157 if !user.contest_started?
157 time_left = "&nbsp;&nbsp;" + (t 'title_bar.contest_not_started')
158 time_left = "&nbsp;&nbsp;" + (t 'title_bar.contest_not_started')
158 else
159 else
159 time_left = "&nbsp;&nbsp;" + (t 'title_bar.remaining_time') +
160 time_left = "&nbsp;&nbsp;" + (t 'title_bar.remaining_time') +
160 " #{format_short_duration(user.contest_time_left)}"
161 " #{format_short_duration(user.contest_time_left)}"
161 end
162 end
162 end
163 end
163
164
164 #
165 #
165 # if the contest is in the anaysis mode
166 # if the contest is in the anaysis mode
@@ -228,119 +228,122
228 available_problems.each {|p| pin[p.id] = true}
228 available_problems.each {|p| pin[p.id] = true}
229 end
229 end
230 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
230 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
231 contest_problems << {
231 contest_problems << {
232 :contest => nil,
232 :contest => nil,
233 :problems => other_avaiable_problems
233 :problems => other_avaiable_problems
234 }
234 }
235 return contest_problems
235 return contest_problems
236 end
236 end
237
237
238 def solve_all_available_problems?
238 def solve_all_available_problems?
239 available_problems.each do |p|
239 available_problems.each do |p|
240 u = self
240 u = self
241 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
241 sub = Submission.find_last_by_user_and_problem(u.id,p.id)
242 return false if !p or !sub or sub.points < p.full_score
242 return false if !p or !sub or sub.points < p.full_score
243 end
243 end
244 return true
244 return true
245 end
245 end
246
246
247 #get a list of available problem
247 #get a list of available problem
248 def available_problems
248 def available_problems
249 # first, we check if this is normal mode
249 # first, we check if this is normal mode
250 if not GraderConfiguration.multicontests?
250 if not GraderConfiguration.multicontests?
251
251
252 #if this is a normal mode
252 #if this is a normal mode
253 #we show problem based on problem_group, if the config said so
253 #we show problem based on problem_group, if the config said so
254 if GraderConfiguration.use_problem_group?
254 if GraderConfiguration.use_problem_group?
255 return available_problems_in_group
255 return available_problems_in_group
256 else
256 else
257 return Problem.available_problems
257 return Problem.available_problems
258 end
258 end
259 else
259 else
260 #this is multi contest mode
260 #this is multi contest mode
261 contest_problems = []
261 contest_problems = []
262 pin = {}
262 pin = {}
263 contests.enabled.each do |contest|
263 contests.enabled.each do |contest|
264 contest.problems.available.each do |problem|
264 contest.problems.available.each do |problem|
265 if not pin.has_key? problem.id
265 if not pin.has_key? problem.id
266 contest_problems << problem
266 contest_problems << problem
267 end
267 end
268 pin[problem.id] = true
268 pin[problem.id] = true
269 end
269 end
270 end
270 end
271 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
271 other_avaiable_problems = Problem.available.find_all {|p| pin[p.id]==nil and p.contests.length==0}
272 return contest_problems + other_avaiable_problems
272 return contest_problems + other_avaiable_problems
273 end
273 end
274 end
274 end
275
275
276 + # new feature, get list of available problem in all enabled group that the user belongs to
276 def available_problems_in_group
277 def available_problems_in_group
277 problem = []
278 problem = []
278 - self.groups.each do |group|
279 + self.groups.where(enabled: true).each do |group|
279 group.problems.where(available: true).each { |p| problem << p }
280 group.problems.where(available: true).each { |p| problem << p }
280 end
281 end
281 problem.uniq!
282 problem.uniq!
282 if problem
283 if problem
283 problem.sort! do |a,b|
284 problem.sort! do |a,b|
284 case
285 case
285 when a.date_added < b.date_added
286 when a.date_added < b.date_added
286 1
287 1
287 when a.date_added > b.date_added
288 when a.date_added > b.date_added
288 -1
289 -1
289 else
290 else
290 a.name <=> b.name
291 a.name <=> b.name
291 end
292 end
292 end
293 end
293 return problem
294 return problem
294 else
295 else
295 return []
296 return []
296 end
297 end
297 end
298 end
298
299
300 + #check if the user has the right to view that problem
301 + #this also consider group based problem policy
299 def can_view_problem?(problem)
302 def can_view_problem?(problem)
300 return true if admin?
303 return true if admin?
301 return available_problems.include? problem
304 return available_problems.include? problem
302 end
305 end
303
306
304 def self.clear_last_login
307 def self.clear_last_login
305 User.update_all(:last_ip => nil)
308 User.update_all(:last_ip => nil)
306 end
309 end
307
310
308 protected
311 protected
309 def encrypt_new_password
312 def encrypt_new_password
310 return if password.blank?
313 return if password.blank?
311 self.salt = (10+rand(90)).to_s
314 self.salt = (10+rand(90)).to_s
312 self.hashed_password = User.encrypt(self.password,self.salt)
315 self.hashed_password = User.encrypt(self.password,self.salt)
313 end
316 end
314
317
315 def assign_default_site
318 def assign_default_site
316 # have to catch error when migrating (because self.site is not available).
319 # have to catch error when migrating (because self.site is not available).
317 begin
320 begin
318 if self.site==nil
321 if self.site==nil
319 self.site = Site.find_by_name('default')
322 self.site = Site.find_by_name('default')
320 if self.site==nil
323 if self.site==nil
321 self.site = Site.find(1) # when 'default has be renamed'
324 self.site = Site.find(1) # when 'default has be renamed'
322 end
325 end
323 end
326 end
324 rescue
327 rescue
325 end
328 end
326 end
329 end
327
330
328 def assign_default_contest
331 def assign_default_contest
329 # have to catch error when migrating (because self.site is not available).
332 # have to catch error when migrating (because self.site is not available).
330 begin
333 begin
331 if self.contests.length == 0
334 if self.contests.length == 0
332 default_contest = Contest.find_by_name(GraderConfiguration['contest.default_contest_name'])
335 default_contest = Contest.find_by_name(GraderConfiguration['contest.default_contest_name'])
333 if default_contest
336 if default_contest
334 self.contests = [default_contest]
337 self.contests = [default_contest]
335 end
338 end
336 end
339 end
337 rescue
340 rescue
338 end
341 end
339 end
342 end
340
343
341 def password_required?
344 def password_required?
342 self.hashed_password.blank? || !self.password.blank?
345 self.hashed_password.blank? || !self.password.blank?
343 end
346 end
344
347
345 def self.encrypt(string,salt)
348 def self.encrypt(string,salt)
346 Digest::SHA1.hexdigest(salt + string)
349 Digest::SHA1.hexdigest(salt + string)
@@ -1,26 +1,26
1
1
2 %tr
2 %tr
3 %td{:align => "center"}
3 %td{:align => "center"}
4 = submission.number
4 = submission.number
5 %td.text-right
5 %td.text-right
6 = link_to "##{submission.id}", submission_path(submission.id)
6 = link_to "##{submission.id}", submission_path(submission.id)
7 %td
7 %td
8 = l submission.submitted_at, format: :long
8 = l submission.submitted_at, format: :long
9 = "( #{time_ago_in_words(submission.submitted_at)} ago)"
9 = "( #{time_ago_in_words(submission.submitted_at)} ago)"
10 %td
10 %td
11 = submission.source_filename
11 = submission.source_filename
12 = " (#{submission.language.pretty_name}) "
12 = " (#{submission.language.pretty_name}) "
13 - = link_to('[load]',{:action => 'source', :id => submission.id})
13 + = link_to '[load]', download_submission_path(submission)
14 %td
14 %td
15 - if submission.graded_at
15 - if submission.graded_at
16 = "Graded at #{format_short_time(submission.graded_at)}."
16 = "Graded at #{format_short_time(submission.graded_at)}."
17 %br/
17 %br/
18 = "Score: #{(submission.points*100/submission.problem.full_score).to_i} " if GraderConfiguration['ui.show_score']
18 = "Score: #{(submission.points*100/submission.problem.full_score).to_i} " if GraderConfiguration['ui.show_score']
19 = " ["
19 = " ["
20 %tt
20 %tt
21 = submission.grader_comment
21 = submission.grader_comment
22 = "]"
22 = "]"
23 %td
23 %td
24 = render :partial => 'compiler_message', :locals => {:compiler_message => submission.compiler_message }
24 = render :partial => 'compiler_message', :locals => {:compiler_message => submission.compiler_message }
25 %td
25 %td
26 = link_to 'Edit', edit_submission_path(submission.id), class: 'btn btn-success'
26 = link_to 'Edit', edit_submission_path(submission.id), class: 'btn btn-success'
@@ -1,16 +1,27
1 = form_for @group do |f|
1 = form_for @group do |f|
2 - if @group.errors.any?
2 - if @group.errors.any?
3 #error_explanation
3 #error_explanation
4 %h2= "#{pluralize(@group.errors.count, "error")} prohibited this group from being saved:"
4 %h2= "#{pluralize(@group.errors.count, "error")} prohibited this group from being saved:"
5 %ul
5 %ul
6 - @group.errors.full_messages.each do |msg|
6 - @group.errors.full_messages.each do |msg|
7 %li= msg
7 %li= msg
8 -
8 + .row
9 - .form-group.field
9 + .col-md-6
10 - = f.label :name
10 + .form-group.field
11 - = f.text_field :name, class: 'form-control'
11 + = f.label :name
12 - .form-group.field
12 + = f.text_field :name, class: 'form-control'
13 - = f.label :description
13 + .row
14 - = f.text_field :description, class: 'form-control'
14 + .col-md-6
15 - .form-group.actions
15 + .form-group.field
16 - = f.submit 'Save', class: 'btn btn-primary'
16 + = f.label :description
17 + = f.text_field :description, class: 'form-control'
18 + .row
19 + .col-md-6
20 + .checkbox
21 + = f.label :enabled do
22 + = f.check_box :enabled
23 + Enabled
24 + .row
25 + .col-md-6
26 + .form-group.actions
27 + = f.submit 'Save', class: 'btn btn-primary'
@@ -1,22 +1,24
1 %h1 Groups
1 %h1 Groups
2
2
3 %p
3 %p
4 = link_to 'New Group', new_group_path, class: 'btn btn-primary'
4 = link_to 'New Group', new_group_path, class: 'btn btn-primary'
5 %table.table.table-hover
5 %table.table.table-hover
6 %thead
6 %thead
7 %tr
7 %tr
8 %th Name
8 %th Name
9 %th Description
9 %th Description
10 + %th Enabled?
10 %th
11 %th
11 %th
12 %th
12
13
13 %tbody
14 %tbody
14 - @groups.each do |group|
15 - @groups.each do |group|
15 - %tr
16 + %tr{:class => "#{(group.enabled?) ? "success" : "danger"}", id: "group-#{group.id}"}
16 %td= group.name
17 %td= group.name
17 %td= group.description
18 %td= group.description
19 + %td= toggle_button(group.enabled?, toggle_group_path(group), "group-enabled-#{group.id}", size: ' ', block: ' ')
18 %td= link_to 'View', group, class: 'btn btn-default'
20 %td= link_to 'View', group, class: 'btn btn-default'
19 %td= link_to 'Destroy', group, :method => :delete, :data => { :confirm => 'Are you sure?' }, class: 'btn btn-danger'
21 %td= link_to 'Destroy', group, :method => :delete, :data => { :confirm => 'Are you sure?' }, class: 'btn btn-danger'
20
22
21 %br
23 %br
22
24
@@ -9,135 +9,135
9
9
10 resources :contests
10 resources :contests
11 resources :sites
11 resources :sites
12 resources :test
12 resources :test
13
13
14 resources :messages do
14 resources :messages do
15 member do
15 member do
16 get 'hide'
16 get 'hide'
17 post 'reply'
17 post 'reply'
18 end
18 end
19 collection do
19 collection do
20 get 'console'
20 get 'console'
21 get 'list_all'
21 get 'list_all'
22 end
22 end
23 end
23 end
24
24
25 resources :announcements do
25 resources :announcements do
26 member do
26 member do
27 get 'toggle','toggle_front'
27 get 'toggle','toggle_front'
28 end
28 end
29 end
29 end
30
30
31 resources :problems do
31 resources :problems do
32 member do
32 member do
33 get 'toggle'
33 get 'toggle'
34 get 'toggle_test'
34 get 'toggle_test'
35 get 'toggle_view_testcase'
35 get 'toggle_view_testcase'
36 get 'stat'
36 get 'stat'
37 end
37 end
38 collection do
38 collection do
39 get 'turn_all_off'
39 get 'turn_all_off'
40 get 'turn_all_on'
40 get 'turn_all_on'
41 get 'import'
41 get 'import'
42 get 'manage'
42 get 'manage'
43 get 'quick_create'
43 get 'quick_create'
44 post 'do_manage'
44 post 'do_manage'
45 post 'do_import'
45 post 'do_import'
46 end
46 end
47 end
47 end
48
48
49 resources :groups do
49 resources :groups do
50 member do
50 member do
51 post 'add_user', to: 'groups#add_user', as: 'add_user'
51 post 'add_user', to: 'groups#add_user', as: 'add_user'
52 delete 'remove_user/:user_id', to: 'groups#remove_user', as: 'remove_user'
52 delete 'remove_user/:user_id', to: 'groups#remove_user', as: 'remove_user'
53 delete 'remove_all_user', to: 'groups#remove_all_user', as: 'remove_all_user'
53 delete 'remove_all_user', to: 'groups#remove_all_user', as: 'remove_all_user'
54 post 'add_problem', to: 'groups#add_problem', as: 'add_problem'
54 post 'add_problem', to: 'groups#add_problem', as: 'add_problem'
55 delete 'remove_problem/:problem_id', to: 'groups#remove_problem', as: 'remove_problem'
55 delete 'remove_problem/:problem_id', to: 'groups#remove_problem', as: 'remove_problem'
56 delete 'remove_all_problem', to: 'groups#remove_all_problem', as: 'remove_all_problem'
56 delete 'remove_all_problem', to: 'groups#remove_all_problem', as: 'remove_all_problem'
57 + get 'toggle'
57 end
58 end
58 collection do
59 collection do
59
60
60 end
61 end
61 end
62 end
62
63
63 resources :testcases, only: [] do
64 resources :testcases, only: [] do
64 member do
65 member do
65 get 'download_input'
66 get 'download_input'
66 get 'download_sol'
67 get 'download_sol'
67 end
68 end
68 collection do
69 collection do
69 get 'show_problem/:problem_id(/:test_num)' => 'testcases#show_problem', as: 'show_problem'
70 get 'show_problem/:problem_id(/:test_num)' => 'testcases#show_problem', as: 'show_problem'
70 end
71 end
71 end
72 end
72
73
73 resources :grader_configuration, controller: 'configurations' do
74 resources :grader_configuration, controller: 'configurations' do
74 collection do
75 collection do
75 get 'set_exam_right(/:value)', action: 'set_exam_right', as: 'set_exam_right'
76 get 'set_exam_right(/:value)', action: 'set_exam_right', as: 'set_exam_right'
76 end
77 end
77 end
78 end
78
79
79 resources :users do
80 resources :users do
80 member do
81 member do
81 get 'toggle_activate', 'toggle_enable'
82 get 'toggle_activate', 'toggle_enable'
82 get 'stat'
83 get 'stat'
83 end
84 end
84 collection do
85 collection do
85 get 'profile'
86 get 'profile'
86 post 'chg_passwd'
87 post 'chg_passwd'
87 end
88 end
88 end
89 end
89
90
90 resources :submissions do
91 resources :submissions do
91 member do
92 member do
92 get 'download'
93 get 'download'
93 get 'compiler_msg'
94 get 'compiler_msg'
94 get 'rejudge'
95 get 'rejudge'
95 - get 'source'
96 end
96 end
97 collection do
97 collection do
98 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
98 get 'prob/:problem_id', to: 'submissions#index', as: 'problem'
99 get 'direct_edit_problem/:problem_id(/:user_id)', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
99 get 'direct_edit_problem/:problem_id(/:user_id)', to: 'submissions#direct_edit_problem', as: 'direct_edit_problem'
100 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
100 get 'get_latest_submission_status/:uid/:pid', to: 'submissions#get_latest_submission_status', as: 'get_latest_submission_status'
101 end
101 end
102 end
102 end
103
103
104
104
105 #user admin
105 #user admin
106 resources :user_admin do
106 resources :user_admin do
107 collection do
107 collection do
108 match 'bulk_manage', via: [:get, :post]
108 match 'bulk_manage', via: [:get, :post]
109 get 'bulk_mail'
109 get 'bulk_mail'
110 get 'user_stat'
110 get 'user_stat'
111 get 'import'
111 get 'import'
112 get 'new_list'
112 get 'new_list'
113 get 'admin'
113 get 'admin'
114 get 'active'
114 get 'active'
115 get 'mass_mailing'
115 get 'mass_mailing'
116 get 'revoke_admin'
116 get 'revoke_admin'
117 post 'grant_admin'
117 post 'grant_admin'
118 match 'create_from_list', via: [:get, :post]
118 match 'create_from_list', via: [:get, :post]
119 match 'random_all_passwords', via: [:get, :post]
119 match 'random_all_passwords', via: [:get, :post]
120 end
120 end
121 member do
121 member do
122 get 'clear_last_ip'
122 get 'clear_last_ip'
123 end
123 end
124 end
124 end
125
125
126 resources :contest_management, only: [:index] do
126 resources :contest_management, only: [:index] do
127 collection do
127 collection do
128 get 'user_stat'
128 get 'user_stat'
129 get 'clear_stat'
129 get 'clear_stat'
130 get 'clear_all_stat'
130 get 'clear_all_stat'
131 get 'change_contest_mode'
131 get 'change_contest_mode'
132 end
132 end
133 end
133 end
134
134
135 #get 'user_admin', to: 'user_admin#index'
135 #get 'user_admin', to: 'user_admin#index'
136 #get 'user_admin/bulk_manage', to: 'user_admin#bulk_manage', as: 'bulk_manage_user_admin'
136 #get 'user_admin/bulk_manage', to: 'user_admin#bulk_manage', as: 'bulk_manage_user_admin'
137 #post 'user_admin', to: 'user_admin#create'
137 #post 'user_admin', to: 'user_admin#create'
138 #delete 'user_admin/:id', to: 'user_admin#destroy', as: 'user_admin_destroy'
138 #delete 'user_admin/:id', to: 'user_admin#destroy', as: 'user_admin_destroy'
139
139
140 #singular resource
140 #singular resource
141 #---- BEWARE ---- singular resource maps to plural controller by default, we can override by provide controller name directly
141 #---- BEWARE ---- singular resource maps to plural controller by default, we can override by provide controller name directly
142 #report
142 #report
143 resource :report, only: [], controller: 'report' do
143 resource :report, only: [], controller: 'report' do
@@ -1,130 +1,131
1 # This file is auto-generated from the current state of the database. Instead
1 # This file is auto-generated from the current state of the database. Instead
2 # of editing this file, please use the migrations feature of Active Record to
2 # of editing this file, please use the migrations feature of Active Record to
3 # incrementally modify your database, and then regenerate this schema definition.
3 # incrementally modify your database, and then regenerate this schema definition.
4 #
4 #
5 # Note that this schema.rb definition is the authoritative source for your
5 # Note that this schema.rb definition is the authoritative source for your
6 # database schema. If you need to create the application database on another
6 # database schema. If you need to create the application database on another
7 # system, you should be using db:schema:load, not running all the migrations
7 # system, you should be using db:schema:load, not running all the migrations
8 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
8 # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9 # you'll amass, the slower it'll run and the greater likelihood for issues).
9 # you'll amass, the slower it'll run and the greater likelihood for issues).
10 #
10 #
11 # It's strongly recommended that you check this file into your version control system.
11 # It's strongly recommended that you check this file into your version control system.
12
12
13 - ActiveRecord::Schema.define(version: 2018_06_12_102327) do
13 + ActiveRecord::Schema.define(version: 2020_08_13_083020) do
14
14
15 create_table "announcements", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
15 create_table "announcements", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
16 t.string "author"
16 t.string "author"
17 t.text "body"
17 t.text "body"
18 t.boolean "published"
18 t.boolean "published"
19 t.datetime "created_at"
19 t.datetime "created_at"
20 t.datetime "updated_at"
20 t.datetime "updated_at"
21 t.boolean "frontpage", default: false
21 t.boolean "frontpage", default: false
22 t.boolean "contest_only", default: false
22 t.boolean "contest_only", default: false
23 t.string "title"
23 t.string "title"
24 t.string "notes"
24 t.string "notes"
25 end
25 end
26
26
27 create_table "contests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
27 create_table "contests", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
28 t.string "title"
28 t.string "title"
29 t.boolean "enabled"
29 t.boolean "enabled"
30 t.datetime "created_at"
30 t.datetime "created_at"
31 t.datetime "updated_at"
31 t.datetime "updated_at"
32 t.string "name"
32 t.string "name"
33 end
33 end
34
34
35 create_table "contests_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
35 create_table "contests_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
36 t.integer "contest_id"
36 t.integer "contest_id"
37 t.integer "problem_id"
37 t.integer "problem_id"
38 end
38 end
39
39
40 create_table "contests_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
40 create_table "contests_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
41 t.integer "contest_id"
41 t.integer "contest_id"
42 t.integer "user_id"
42 t.integer "user_id"
43 end
43 end
44
44
45 create_table "countries", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
45 create_table "countries", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
46 t.string "name"
46 t.string "name"
47 t.datetime "created_at"
47 t.datetime "created_at"
48 t.datetime "updated_at"
48 t.datetime "updated_at"
49 end
49 end
50
50
51 create_table "descriptions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
51 create_table "descriptions", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
52 t.text "body"
52 t.text "body"
53 t.boolean "markdowned"
53 t.boolean "markdowned"
54 t.datetime "created_at"
54 t.datetime "created_at"
55 t.datetime "updated_at"
55 t.datetime "updated_at"
56 end
56 end
57
57
58 create_table "grader_configurations", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
58 create_table "grader_configurations", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
59 t.string "key"
59 t.string "key"
60 t.string "value_type"
60 t.string "value_type"
61 t.string "value"
61 t.string "value"
62 t.datetime "created_at"
62 t.datetime "created_at"
63 t.datetime "updated_at"
63 t.datetime "updated_at"
64 t.text "description"
64 t.text "description"
65 end
65 end
66
66
67 create_table "grader_processes", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
67 create_table "grader_processes", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
68 t.string "host"
68 t.string "host"
69 t.integer "pid"
69 t.integer "pid"
70 t.string "mode"
70 t.string "mode"
71 t.boolean "active"
71 t.boolean "active"
72 t.datetime "created_at"
72 t.datetime "created_at"
73 t.datetime "updated_at"
73 t.datetime "updated_at"
74 t.integer "task_id"
74 t.integer "task_id"
75 t.string "task_type"
75 t.string "task_type"
76 t.boolean "terminated"
76 t.boolean "terminated"
77 t.index ["host", "pid"], name: "index_grader_processes_on_host_and_pid"
77 t.index ["host", "pid"], name: "index_grader_processes_on_host_and_pid"
78 end
78 end
79
79
80 create_table "groups", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
80 create_table "groups", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
81 t.string "name"
81 t.string "name"
82 t.string "description"
82 t.string "description"
83 + t.boolean "enabled", default: true
83 end
84 end
84
85
85 create_table "groups_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
86 create_table "groups_problems", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
86 t.integer "problem_id", null: false
87 t.integer "problem_id", null: false
87 t.integer "group_id", null: false
88 t.integer "group_id", null: false
88 t.index ["group_id", "problem_id"], name: "index_groups_problems_on_group_id_and_problem_id"
89 t.index ["group_id", "problem_id"], name: "index_groups_problems_on_group_id_and_problem_id"
89 end
90 end
90
91
91 create_table "groups_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
92 create_table "groups_users", id: false, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
92 t.integer "group_id", null: false
93 t.integer "group_id", null: false
93 t.integer "user_id", null: false
94 t.integer "user_id", null: false
94 t.index ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id"
95 t.index ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id"
95 end
96 end
96
97
97 create_table "heart_beats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
98 create_table "heart_beats", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
98 t.integer "user_id"
99 t.integer "user_id"
99 t.string "ip_address"
100 t.string "ip_address"
100 t.datetime "created_at"
101 t.datetime "created_at"
101 t.datetime "updated_at"
102 t.datetime "updated_at"
102 t.string "status"
103 t.string "status"
103 t.index ["updated_at"], name: "index_heart_beats_on_updated_at"
104 t.index ["updated_at"], name: "index_heart_beats_on_updated_at"
104 end
105 end
105
106
106 create_table "languages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
107 create_table "languages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
107 t.string "name", limit: 10
108 t.string "name", limit: 10
108 t.string "pretty_name"
109 t.string "pretty_name"
109 t.string "ext", limit: 10
110 t.string "ext", limit: 10
110 t.string "common_ext"
111 t.string "common_ext"
111 end
112 end
112
113
113 create_table "logins", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
114 create_table "logins", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
114 t.integer "user_id"
115 t.integer "user_id"
115 t.string "ip_address"
116 t.string "ip_address"
116 t.datetime "created_at"
117 t.datetime "created_at"
117 t.datetime "updated_at"
118 t.datetime "updated_at"
118 end
119 end
119
120
120 create_table "messages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
121 create_table "messages", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
121 t.integer "sender_id"
122 t.integer "sender_id"
122 t.integer "receiver_id"
123 t.integer "receiver_id"
123 t.integer "replying_message_id"
124 t.integer "replying_message_id"
124 t.text "body"
125 t.text "body"
125 t.boolean "replied"
126 t.boolean "replied"
126 t.datetime "created_at"
127 t.datetime "created_at"
127 t.datetime "updated_at"
128 t.datetime "updated_at"
128 end
129 end
129
130
130 create_table "problems", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
131 create_table "problems", id: :integer, options: "ENGINE=InnoDB DEFAULT CHARSET=latin1", force: :cascade do |t|
You need to be logged in to leave comments. Login now