Description:
add tags
Commit status:
[Not Reviewed]
References:
Diff options:
Comments:
0 Commit comments
0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
r700:757ebc0ccd63 - - 7 files changed: 56 inserted, 29 deleted
@@ -164,143 +164,147 | |||
|
164 | 164 | unless @problem.available or session[:admin] |
|
165 | 165 | redirect_to :controller => 'main', :action => 'list' |
|
166 | 166 | return |
|
167 | 167 | end |
|
168 | 168 | @submissions = Submission.includes(:user).includes(:language).where(problem_id: params[:id]).order(:user_id,:id) |
|
169 | 169 | |
|
170 | 170 | #stat summary |
|
171 | 171 | range =65 |
|
172 | 172 | @histogram = { data: Array.new(range,0), summary: {} } |
|
173 | 173 | user = Hash.new(0) |
|
174 | 174 | @submissions.find_each do |sub| |
|
175 | 175 | d = (DateTime.now.in_time_zone - sub.submitted_at) / 24 / 60 / 60 |
|
176 | 176 | @histogram[:data][d.to_i] += 1 if d < range |
|
177 | 177 | user[sub.user_id] = [user[sub.user_id], ((sub.try(:points) || 0) >= @problem.full_score) ? 1 : 0].max |
|
178 | 178 | end |
|
179 | 179 | @histogram[:summary][:max] = [@histogram[:data].max,1].max |
|
180 | 180 | |
|
181 | 181 | @summary = { attempt: user.count, solve: 0 } |
|
182 | 182 | user.each_value { |v| @summary[:solve] += 1 if v == 1 } |
|
183 | 183 | end |
|
184 | 184 | |
|
185 | 185 | def manage |
|
186 | 186 | @problems = Problem.order(date_added: :desc) |
|
187 | 187 | end |
|
188 | 188 | |
|
189 | 189 | def do_manage |
|
190 | 190 | if params.has_key? 'change_date_added' |
|
191 | 191 | change_date_added |
|
192 | 192 | elsif params.has_key? 'add_to_contest' |
|
193 | 193 | add_to_contest |
|
194 | 194 | elsif params.has_key? 'enable_problem' |
|
195 | 195 | set_available(true) |
|
196 | 196 | elsif params.has_key? 'disable_problem' |
|
197 | 197 | set_available(false) |
|
198 | 198 | elsif params.has_key? 'add_group' |
|
199 | 199 | group = Group.find(params[:group_id]) |
|
200 | 200 | ok = [] |
|
201 | 201 | failed = [] |
|
202 | 202 | get_problems_from_params.each do |p| |
|
203 | 203 | begin |
|
204 | 204 | group.problems << p |
|
205 | 205 | ok << p.full_name |
|
206 | 206 | rescue => e |
|
207 | 207 | failed << p.full_name |
|
208 | 208 | end |
|
209 | 209 | end |
|
210 | 210 | flash[:success] = "The following problems are added to the group #{group.name}: " + ok.join(', ') if ok.count > 0 |
|
211 | 211 | flash[:alert] = "The following problems are already in the group #{group.name}: " + failed.join(', ') if failed.count > 0 |
|
212 | + elsif params.has_key? 'add_tags' | |
|
213 | + get_problems_from_params.each do |p| | |
|
214 | + p.tag_ids += params[:tag_ids] | |
|
215 | + end | |
|
212 | 216 | end |
|
213 | 217 | |
|
214 | 218 | redirect_to :action => 'manage' |
|
215 | 219 | end |
|
216 | 220 | |
|
217 | 221 | def import |
|
218 | 222 | @allow_test_pair_import = allow_test_pair_import? |
|
219 | 223 | end |
|
220 | 224 | |
|
221 | 225 | def do_import |
|
222 | 226 | old_problem = Problem.find_by_name(params[:name]) |
|
223 | 227 | if !allow_test_pair_import? and params.has_key? :import_to_db |
|
224 | 228 | params.delete :import_to_db |
|
225 | 229 | end |
|
226 | 230 | @problem, import_log = Problem.create_from_import_form_params(params, |
|
227 | 231 | old_problem) |
|
228 | 232 | |
|
229 | 233 | if !@problem.errors.empty? |
|
230 | 234 | render :action => 'import' and return |
|
231 | 235 | end |
|
232 | 236 | |
|
233 | 237 | if old_problem!=nil |
|
234 | 238 | flash[:notice] = "The test data has been replaced for problem #{@problem.name}" |
|
235 | 239 | end |
|
236 | 240 | @log = import_log |
|
237 | 241 | end |
|
238 | 242 | |
|
239 | 243 | def remove_contest |
|
240 | 244 | problem = Problem.find(params[:id]) |
|
241 | 245 | contest = Contest.find(params[:contest_id]) |
|
242 | 246 | if problem!=nil and contest!=nil |
|
243 | 247 | problem.contests.delete(contest) |
|
244 | 248 | end |
|
245 | 249 | redirect_to :action => 'manage' |
|
246 | 250 | end |
|
247 | 251 | |
|
248 | 252 | ################################## |
|
249 | 253 | protected |
|
250 | 254 | |
|
251 | 255 | def allow_test_pair_import? |
|
252 | 256 | if defined? ALLOW_TEST_PAIR_IMPORT |
|
253 | 257 | return ALLOW_TEST_PAIR_IMPORT |
|
254 | 258 | else |
|
255 | 259 | return false |
|
256 | 260 | end |
|
257 | 261 | end |
|
258 | 262 | |
|
259 | 263 | def change_date_added |
|
260 | 264 | problems = get_problems_from_params |
|
261 | 265 | date = Date.parse(params[:date_added]) |
|
262 | 266 | problems.each do |p| |
|
263 | 267 | p.date_added = date |
|
264 | 268 | p.save |
|
265 | 269 | end |
|
266 | 270 | end |
|
267 | 271 | |
|
268 | 272 | def add_to_contest |
|
269 | 273 | problems = get_problems_from_params |
|
270 | 274 | contest = Contest.find(params[:contest][:id]) |
|
271 | 275 | if contest!=nil and contest.enabled |
|
272 | 276 | problems.each do |p| |
|
273 | 277 | p.contests << contest |
|
274 | 278 | end |
|
275 | 279 | end |
|
276 | 280 | end |
|
277 | 281 | |
|
278 | 282 | def set_available(avail) |
|
279 | 283 | problems = get_problems_from_params |
|
280 | 284 | problems.each do |p| |
|
281 | 285 | p.available = avail |
|
282 | 286 | p.save |
|
283 | 287 | end |
|
284 | 288 | end |
|
285 | 289 | |
|
286 | 290 | def get_problems_from_params |
|
287 | 291 | problems = [] |
|
288 | 292 | params.keys.each do |k| |
|
289 | 293 | if k.index('prob-')==0 |
|
290 | 294 | name, id, order = k.split('-') |
|
291 | 295 | problems << Problem.find(id) |
|
292 | 296 | end |
|
293 | 297 | end |
|
294 | 298 | problems |
|
295 | 299 | end |
|
296 | 300 | |
|
297 | 301 | def get_problems_stat |
|
298 | 302 | end |
|
299 | 303 | |
|
300 | 304 | private |
|
301 | 305 | |
|
302 | 306 | def problem_params |
|
303 | - params.require(:problem).permit(:name, :full_name, :full_score, :date_added, :available, :test_allowed,:output_only, :url, :description) | |
|
307 | + params.require(:problem).permit(:name, :full_name, :full_score, :date_added, :available, :test_allowed,:output_only, :url, :description, tag_ids:[]) | |
|
304 | 308 | end |
|
305 | 309 | |
|
306 | 310 | end |
@@ -1,58 +1,60 | |||
|
1 | 1 | class TagsController < ApplicationController |
|
2 | 2 | before_action :set_tag, only: [:show, :edit, :update, :destroy] |
|
3 | 3 | |
|
4 | 4 | # GET /tags |
|
5 | 5 | def index |
|
6 | 6 | @tags = Tag.all |
|
7 | 7 | end |
|
8 | 8 | |
|
9 | 9 | # GET /tags/1 |
|
10 | 10 | def show |
|
11 | 11 | end |
|
12 | 12 | |
|
13 | 13 | # GET /tags/new |
|
14 | 14 | def new |
|
15 | 15 | @tag = Tag.new |
|
16 | 16 | end |
|
17 | 17 | |
|
18 | 18 | # GET /tags/1/edit |
|
19 | 19 | def edit |
|
20 | 20 | end |
|
21 | 21 | |
|
22 | 22 | # POST /tags |
|
23 | 23 | def create |
|
24 | 24 | @tag = Tag.new(tag_params) |
|
25 | 25 | |
|
26 | 26 | if @tag.save |
|
27 | 27 | redirect_to @tag, notice: 'Tag was successfully created.' |
|
28 | 28 | else |
|
29 | 29 | render :new |
|
30 | 30 | end |
|
31 | 31 | end |
|
32 | 32 | |
|
33 | 33 | # PATCH/PUT /tags/1 |
|
34 | 34 | def update |
|
35 | 35 | if @tag.update(tag_params) |
|
36 | 36 | redirect_to @tag, notice: 'Tag was successfully updated.' |
|
37 | 37 | else |
|
38 | 38 | render :edit |
|
39 | 39 | end |
|
40 | 40 | end |
|
41 | 41 | |
|
42 | 42 | # DELETE /tags/1 |
|
43 | 43 | def destroy |
|
44 | + #remove any association | |
|
45 | + ProblemTag.where(tag_id: @tag.id).destroy_all | |
|
44 | 46 | @tag.destroy |
|
45 | 47 | redirect_to tags_url, notice: 'Tag was successfully destroyed.' |
|
46 | 48 | end |
|
47 | 49 | |
|
48 | 50 | private |
|
49 | 51 | # Use callbacks to share common setup or constraints between actions. |
|
50 | 52 | def set_tag |
|
51 | 53 | @tag = Tag.find(params[:id]) |
|
52 | 54 | end |
|
53 | 55 | |
|
54 | 56 | # Only allow a trusted parameter "white list" through. |
|
55 | 57 | def tag_params |
|
56 | 58 | params.require(:tag).permit(:name, :description, :public) |
|
57 | 59 | end |
|
58 | 60 | end |
@@ -1,94 +1,95 | |||
|
1 | 1 | %header.navbar.navbar-default.navbar-fixed-top |
|
2 | 2 | %nav |
|
3 | 3 | .container-fluid |
|
4 | 4 | .navbar-header |
|
5 | 5 | %button.navbar-toggle.collapsed{ data: {toggle: 'collapse', target: '#navbar-collapse'} } |
|
6 | 6 | %span.sr-only Togggle Navigation |
|
7 | 7 | %span.icon-bar |
|
8 | 8 | %span.icon-bar |
|
9 | 9 | %span.icon-bar |
|
10 | 10 | %a.navbar-brand{href: main_list_path} |
|
11 | 11 | %span.glyphicon.glyphicon-home |
|
12 | 12 | MAIN |
|
13 | 13 | .collapse.navbar-collapse#navbar-collapse |
|
14 | 14 | %ul.nav.navbar-nav |
|
15 | 15 | / submission |
|
16 | 16 | - if (@current_user!=nil) and (GraderConfiguration.show_tasks_to?(@current_user)) |
|
17 | 17 | %li.dropdown |
|
18 | 18 | %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"} |
|
19 | 19 | = "#{I18n.t 'menu.submissions'}" |
|
20 | 20 | %span.caret |
|
21 | 21 | %ul.dropdown-menu |
|
22 | 22 | = add_menu("View", 'submissions', 'index') |
|
23 | 23 | = add_menu("Self Test", 'test', 'index') |
|
24 | 24 | / hall of fame |
|
25 | 25 | - if GraderConfiguration['right.user_hall_of_fame'] |
|
26 | 26 | = add_menu("#{I18n.t 'menu.hall_of_fame'}", 'report', 'problem_hof') |
|
27 | 27 | / display MODE button (with countdown in contest mode) |
|
28 | 28 | - if GraderConfiguration.analysis_mode? |
|
29 | 29 | %div.navbar-btn.btn.btn-success#countdown= "ANALYSIS MODE" |
|
30 | 30 | - elsif GraderConfiguration.time_limit_mode? |
|
31 | 31 | - if @current_user.contest_finished? |
|
32 | 32 | %div.navbar-btn.btn.btn-danger#countdown= "Contest is over" |
|
33 | 33 | - elsif !@current_user.contest_started? |
|
34 | 34 | %div.navbar-btn.btn.btn-primary#countdown= (t 'title_bar.contest_not_started') |
|
35 | 35 | - else |
|
36 | 36 | %div.navbar-btn.btn.btn-primary#countdown asdf |
|
37 | 37 | :javascript |
|
38 | 38 | $("#countdown").countdown({until: "+#{@current_user.contest_time_left.to_i}s", layout: 'Time left: {hnn}:{mnn}:{snn}'}); |
|
39 | 39 | / admin section |
|
40 | 40 | - if (@current_user!=nil) and (session[:admin]) |
|
41 | 41 | / management |
|
42 | 42 | %li.dropdown |
|
43 | 43 | %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"} |
|
44 | 44 | Manage |
|
45 | 45 | %span.caret |
|
46 | 46 | %ul.dropdown-menu |
|
47 | 47 | = add_menu( 'Announcements', 'announcements', 'index') |
|
48 | 48 | = add_menu( 'Problems', 'problems', 'index') |
|
49 | + = add_menu( 'Tags', 'tags', 'index') | |
|
49 | 50 | = add_menu( 'Users', 'user_admin', 'index') |
|
50 | 51 | = add_menu( 'User Groups', 'groups', 'index') |
|
51 | 52 | = add_menu( 'Graders', 'graders', 'list') |
|
52 | 53 | = add_menu( 'Message ', 'messages', 'console') |
|
53 | 54 | %li.divider{role: 'separator'} |
|
54 | 55 | = add_menu( 'System config', 'configurations', 'index') |
|
55 | 56 | %li.divider{role: 'separator'} |
|
56 | 57 | = add_menu( 'Sites', 'sites', 'index') |
|
57 | 58 | = add_menu( 'Contests', 'contest_management', 'index') |
|
58 | 59 | / report |
|
59 | 60 | %li.dropdown |
|
60 | 61 | %a.dropdown-toggle{href: '#', data: {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"} |
|
61 | 62 | Report |
|
62 | 63 | %span.caret |
|
63 | 64 | %ul.dropdown-menu |
|
64 | 65 | = add_menu( 'Current Score', 'report', 'current_score') |
|
65 | 66 | = add_menu( 'Score Report', 'report', 'max_score') |
|
66 | 67 | = add_menu( 'Report', 'report', 'multiple_login') |
|
67 | 68 | - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0 |
|
68 | 69 | =link_to "#{ungraded} backlogs!", |
|
69 | 70 | grader_list_path, |
|
70 | 71 | class: 'navbar-btn btn btn-default btn-warning', data: {toggle: 'tooltip'},title: 'Number of ungraded submission' |
|
71 | 72 | |
|
72 | 73 | %ul.nav.navbar-nav.navbar-right |
|
73 | 74 | = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-question-sign')}".html_safe, 'main', 'help') |
|
74 | 75 | = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-comment')}".html_safe, 'messages', 'list', {title: I18n.t('menu.messages'), data: {toggle: 'tooltip'}}) |
|
75 | 76 | - if GraderConfiguration['system.user_setting_enabled'] |
|
76 | 77 | = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-cog')}".html_safe, 'users', 'index', {title: I18n.t('menu.settings'), data: {toggle: 'tooltip'}}) |
|
77 | 78 | = add_menu("#{content_tag(:span,'',class: 'glyphicon glyphicon-log-out')} #{@current_user.full_name}".html_safe, 'main', 'login', {title: I18n.t('menu.log_out'), data: {toggle: 'tooltip'}}) |
|
78 | 79 | |
|
79 | 80 | / |
|
80 | 81 | - if (@current_user!=nil) and (session[:admin]) |
|
81 | 82 | %nav.navbar.navbar-fixed-top.navbar-inverse.secondnavbar |
|
82 | 83 | .container-fluid |
|
83 | 84 | .collapse.navbar-collapse |
|
84 | 85 | %ul.nav.navbar-nav |
|
85 | 86 | = add_menu( '[Announcements]', 'announcements', 'index') |
|
86 | 87 | = add_menu( '[Msg console]', 'messages', 'console') |
|
87 | 88 | = add_menu( '[Problems]', 'problems', 'index') |
|
88 | 89 | = add_menu( '[Users]', 'user_admin', 'index') |
|
89 | 90 | = add_menu( '[Results]', 'user_admin', 'user_stat') |
|
90 | 91 | = add_menu( '[Report]', 'report', 'multiple_login') |
|
91 | 92 | = add_menu( '[Graders]', 'graders', 'list') |
|
92 | 93 | = add_menu( '[Contests]', 'contest_management', 'index') |
|
93 | 94 | = add_menu( '[Sites]', 'sites', 'index') |
|
94 | 95 | = add_menu( '[System config]', 'configurations', 'index') |
@@ -1,52 +1,55 | |||
|
1 | 1 | = error_messages_for 'problem' |
|
2 | 2 | / [form:problem] |
|
3 | 3 | .form-group |
|
4 | 4 | %label{:for => "problem_name"} Name |
|
5 | 5 | = text_field 'problem', 'name', class: 'form-control' |
|
6 | 6 | %small |
|
7 | 7 | Do not directly edit the problem name, unless you know what you are doing. If you want to change the name, use the name change button in the problem management menu instead. |
|
8 | 8 | .form-group |
|
9 | 9 | %label{:for => "problem_full_name"} Full name |
|
10 | 10 | = text_field 'problem', 'full_name', class: 'form-control' |
|
11 | 11 | .form-group |
|
12 | 12 | %label{:for => "problem_full_score"} Full score |
|
13 | 13 | = text_field 'problem', 'full_score', class: 'form-control' |
|
14 | 14 | .form-group |
|
15 | + %label{:for => "problem_full_score"} Tags | |
|
16 | + = collection_select(:problem, :tag_ids, Tag.all, :id, :name, {}, {multiple: true, class: 'form-control select2'}) | |
|
17 | + .form-group | |
|
15 | 18 | %label{:for => "problem_date_added"} Date added |
|
16 | 19 | = date_select 'problem', 'date_added', class: 'form-control' |
|
17 | 20 | - # TODO: these should be put in model Problem, but I can't think of |
|
18 | 21 | - # nice default values for them. These values look fine only |
|
19 | 22 | - # in this case (of lazily adding new problems). |
|
20 | 23 | - @problem.available = true if @problem!=nil and @problem.available==nil |
|
21 | 24 | - @problem.test_allowed = true if @problem!=nil and @problem.test_allowed==nil |
|
22 | 25 | - @problem.output_only = false if @problem!=nil and @problem.output_only==nil |
|
23 | 26 | .checkbox |
|
24 | 27 | %label{:for => "problem_available"} |
|
25 | 28 | = check_box :problem, :available |
|
26 | 29 | Available? |
|
27 | 30 | .checkbox |
|
28 | 31 | %label{:for => "problem_test_allowed"} |
|
29 | 32 | = check_box :problem, :test_allowed |
|
30 | 33 | Test allowed? |
|
31 | 34 | .checkbox |
|
32 | 35 | %label{:for => "problem_output_only"} |
|
33 | 36 | = check_box :problem, :output_only |
|
34 | 37 | Output only? |
|
35 | 38 | = error_messages_for 'description' |
|
36 | 39 | .form-group |
|
37 | 40 | %label{:for => "description_body"} Description |
|
38 | 41 | %br/ |
|
39 | 42 | = text_area :description, :body, :rows => 10, :cols => 80,class: 'form-control' |
|
40 | 43 | .form-group |
|
41 | 44 | %label{:for => "description_markdowned"} Markdowned? |
|
42 | 45 | = select "description", | |
|
43 | 46 | "markdowned", | |
|
44 | 47 | [['True',true],['False',false]], | |
|
45 | 48 | {:selected => (@description) ? @description.markdowned : false } | |
|
46 | 49 | .form-group |
|
47 | 50 | %label{:for => "problem_url"} URL |
|
48 | 51 | %br/ |
|
49 | 52 | = text_field 'problem', 'url',class: 'form-control' |
|
50 | 53 | %p |
|
51 | 54 | Task PDF #{file_field_tag 'file'} |
|
52 | 55 | / [eoform:problem] |
@@ -1,60 +1,65 | |||
|
1 | 1 | - content_for :head do |
|
2 | 2 | = stylesheet_link_tag 'problems' |
|
3 | 3 | %h1 Problems |
|
4 | 4 | %p |
|
5 | 5 | = link_to 'Import problems', {:action => 'import'}, class: 'btn btn-success btn-sm' |
|
6 | 6 | = link_to 'New problem', new_problem_path, class: 'btn btn-success btn-sm' |
|
7 | 7 | = link_to 'Bulk Manage', { action: 'manage'}, class: 'btn btn-info btn-sm' |
|
8 | 8 | = link_to 'Turn off all problems', {:action => 'turn_all_off'}, class: 'btn btn-default btn-sm' |
|
9 | 9 | = link_to 'Turn on all problems', {:action => 'turn_all_on'}, class: 'btn btn-default btn-sm' |
|
10 | 10 | .submitbox |
|
11 | 11 | = form_tag :action => 'quick_create' do |
|
12 | 12 | %b Quick New: |
|
13 | 13 | %label{:for => "problem_name"} Name |
|
14 | 14 | = text_field 'problem', 'name' |
|
15 | 15 | | |
|
16 | 16 | %label{:for => "problem_full_name"} Full name |
|
17 | 17 | = text_field 'problem', 'full_name' |
|
18 | 18 | = submit_tag "Create" |
|
19 | 19 | %table.table.table-condense.table-hover |
|
20 | 20 | %thead |
|
21 | 21 | %th Name |
|
22 | 22 | %th Full name |
|
23 | 23 | %th.text-right Full score |
|
24 | + %th Tags | |
|
24 | 25 | %th |
|
25 | 26 | Submit |
|
26 | 27 | %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Admin can always submit to any problem' } [?] |
|
27 | 28 | %th Date added |
|
28 | 29 | %th.text-center |
|
29 | 30 | Avail? |
|
30 | 31 | %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user submits to this problem?' } [?] |
|
31 | 32 | %th.text-center |
|
32 | 33 | View Data? |
|
33 | 34 | %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user view the testcase of this problem?' } [?] |
|
34 | 35 | %th.text-center |
|
35 | 36 | Test? |
|
36 | 37 | %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user uses test interface on this problem?' } [?] |
|
37 | 38 | - if GraderConfiguration.multicontests? |
|
38 | 39 | %th Contests |
|
39 | 40 | - for problem in @problems |
|
40 | 41 | %tr{:class => "#{(problem.available) ? "success" : "danger"}", :id => "prob-#{problem.id}", :name => "prob-#{problem.id}"} |
|
41 | 42 | - @problem=problem |
|
42 | 43 | %td= problem.name #in_place_editor_field :problem, :name, {}, :rows=>1 |
|
43 | 44 | %td |
|
44 | 45 | = problem.full_name #in_place_editor_field :problem, :full_name, {}, :rows=>1 |
|
45 | 46 | = link_to_description_if_any "[#{t 'main.problem_desc'}] <span class='glyphicon glyphicon-file'></span>".html_safe, problem |
|
46 | 47 | %td.text-right= problem.full_score #in_place_editor_field :problem, :full_score, {}, :rows=>1 |
|
48 | + %td | |
|
49 | + - problem.tags.each do |t| | |
|
50 | + - #%button.btn.btn-default.btn-xs= t.name | |
|
51 | + %span.label.label-default= t.name | |
|
47 | 52 | %td= link_to "Submit", direct_edit_problem_submissions_path(problem,@current_user.id), class: 'btn btn-xs btn-primary' |
|
48 | 53 | %td= problem.date_added |
|
49 | 54 | %td= toggle_button(@problem.available?, toggle_problem_path(@problem), "problem-avail-#{@problem.id}") |
|
50 | 55 | %td= toggle_button(@problem.view_testcase?, toggle_view_testcase_problem_path(@problem), "problem-view-testcase-#{@problem.id}") |
|
51 | 56 | %td= toggle_button(@problem.test_allowed?, toggle_test_problem_path(@problem), "problem-test-#{@problem.id}") |
|
52 | 57 | - if GraderConfiguration.multicontests? |
|
53 | 58 | %td |
|
54 | 59 | = problem.contests.collect { |c| c.name }.join(', ') |
|
55 | 60 | %td= link_to 'Stat', {:action => 'stat', :id => problem.id}, class: 'btn btn-info btn-xs btn-block' |
|
56 | 61 | %td= link_to 'Show', {:action => 'show', :id => problem}, class: 'btn btn-info btn-xs btn-block' |
|
57 | 62 | %td= link_to 'Edit', {:action => 'edit', :id => problem}, class: 'btn btn-info btn-xs btn-block' |
|
58 | 63 | %td= link_to 'Destroy', { :action => 'destroy', :id => problem }, :confirm => 'Are you sure?', :method => :delete, class: 'btn btn-danger btn-xs btn-block' |
|
59 | 64 | %br/ |
|
60 | 65 | = link_to '[New problem]', :action => 'new' |
@@ -4,104 +4,115 | |||
|
4 | 4 | |
|
5 | 5 | :javascript |
|
6 | 6 | $(document).ready( function() { |
|
7 | 7 | function shiftclick(start,stop,value) { |
|
8 | 8 | $('tr input').each( function(id,input) { |
|
9 | 9 | var $input=$(input); |
|
10 | 10 | var iid=parseInt($input.attr('id').split('-')[2]); |
|
11 | 11 | if(iid>=start&&iid<=stop){ |
|
12 | 12 | $input.prop('checked',value) |
|
13 | 13 | } |
|
14 | 14 | }); |
|
15 | 15 | } |
|
16 | 16 | |
|
17 | 17 | $('tr input').click( function(e) { |
|
18 | 18 | if (e.shiftKey) { |
|
19 | 19 | stop = parseInt($(this).attr('id').split('-')[2]); |
|
20 | 20 | var orig_stop = stop |
|
21 | 21 | if (typeof start !== 'undefined') { |
|
22 | 22 | if (start > stop) { |
|
23 | 23 | var tmp = start; |
|
24 | 24 | start = stop; |
|
25 | 25 | stop = tmp; |
|
26 | 26 | } |
|
27 | 27 | shiftclick(start,stop,$(this).is(':checked') ) |
|
28 | 28 | } |
|
29 | 29 | start = orig_stop |
|
30 | 30 | } else { |
|
31 | 31 | start = parseInt($(this).attr('id').split('-')[2]); |
|
32 | 32 | } |
|
33 | 33 | }); |
|
34 | 34 | }); |
|
35 | 35 | |
|
36 | 36 | |
|
37 | 37 | %h1 Manage problems |
|
38 | 38 | |
|
39 | 39 | %p= link_to '[Back to problem list]', problems_path |
|
40 | 40 | |
|
41 | 41 | = form_tag :action=>'do_manage' do |
|
42 | 42 | .panel.panel-primary |
|
43 | 43 | .panel-heading |
|
44 | 44 | Action |
|
45 | 45 | .panel-body |
|
46 | 46 | .submit-box |
|
47 | 47 | What do you want to do to the selected problem? |
|
48 | 48 | %br/ |
|
49 | 49 | (You can shift-click to select a range of problems) |
|
50 | 50 | %ul.form-inline |
|
51 | 51 | %li |
|
52 |
- Change |
|
|
52 | + Change "Date added" to | |
|
53 | 53 | .input-group.date |
|
54 | 54 | = text_field_tag :date_added, class: 'form-control' |
|
55 | 55 | %span.input-group-addon |
|
56 | 56 | %span.glyphicon.glyphicon-calendar |
|
57 | 57 | -# = select_date Date.current, :prefix => 'date_added' |
|
58 | 58 | |
|
59 | 59 | = submit_tag 'Change', :name => 'change_date_added', class: 'btn btn-primary btn-sm' |
|
60 | 60 | %li |
|
61 |
- Set |
|
|
61 | + Set "Available" to | |
|
62 | 62 | = submit_tag 'True', :name => 'enable_problem', class: 'btn btn-primary btn-sm' |
|
63 | 63 | = submit_tag 'False', :name => 'disable_problem', class: 'btn btn-primary btn-sm' |
|
64 | 64 | |
|
65 | 65 | - if GraderConfiguration.multicontests? |
|
66 | 66 | %li |
|
67 | - Add to | |
|
67 | + Add selected problems to contest | |
|
68 | 68 | = select("contest","id",Contest.all.collect {|c| [c.title, c.id]}) |
|
69 | 69 | = submit_tag 'Add', :name => 'add_to_contest', class: 'btn btn-primary btn-sm' |
|
70 | 70 | %li |
|
71 | - Add problems to group | |
|
71 | + Add selected problems to user group | |
|
72 | 72 | = select_tag "group_id", options_from_collection_for_select( Group.all, 'id','name',params[:group_name]), id: 'group_name',class: 'select2' |
|
73 |
- = submit_tag 'Add', name: 'add_group', class: 'btn btn- |
|
|
74 | - | |
|
73 | + = submit_tag 'Add', name: 'add_group', class: 'btn btn-primary' | |
|
74 | + %li | |
|
75 | + Add the following tags to the selected problems | |
|
76 | + = select_tag "tag_ids", options_from_collection_for_select( Tag.all, 'id','name'), id: 'tags_name',class: 'select2', multiple: true, data: {placeholder: 'Select tags by clicking', width: "200px"} | |
|
77 | + = submit_tag 'Add', name: 'add_tags', class: 'btn btn-primary' | |
|
75 | 78 | |
|
76 | - %table.table.table-hover | |
|
77 | - %tr{style: "text-align: left;"} | |
|
78 | - %th= check_box_tag 'select_all' | |
|
79 | - %th Name | |
|
80 |
- %th |
|
|
81 |
- %th |
|
|
82 |
- %th |
|
|
83 | - - if GraderConfiguration.multicontests? | |
|
84 |
- %th |
|
|
79 | + %table.table.table-hover.datatable | |
|
80 | + %thead | |
|
81 | + %tr{style: "text-align: left;"} | |
|
82 | + %th= check_box_tag 'select_all' | |
|
83 | + %th Name | |
|
84 | + %th Full name | |
|
85 | + %th Tags | |
|
86 | + %th Available | |
|
87 | + %th Date added | |
|
88 | + - if GraderConfiguration.multicontests? | |
|
89 | + %th Contests | |
|
85 | 90 | |
|
86 | - - num = 0 | |
|
87 | - - for problem in @problems | |
|
88 | - - num += 1 | |
|
89 | - %tr{:id => "row-prob-#{problem.id}", :name=> "prob-#{problem.id}"} | |
|
90 | - %td= check_box_tag "prob-#{problem.id}-#{num}" | |
|
91 | - %td= problem.name | |
|
92 |
- %td= problem. |
|
|
93 |
- %td= problem. |
|
|
94 | - %td= problem.date_added | |
|
95 | - - if GraderConfiguration.multicontests? | |
|
91 | + %tbody | |
|
92 | + - num = 0 | |
|
93 | + - for problem in @problems | |
|
94 | + - num += 1 | |
|
95 | + %tr{:id => "row-prob-#{problem.id}", :name=> "prob-#{problem.id}"} | |
|
96 | + %td= check_box_tag "prob-#{problem.id}-#{num}" | |
|
97 | + %td= problem.name | |
|
98 | + %td= problem.full_name | |
|
96 | 99 | %td |
|
97 |
- - problem. |
|
|
98 | - = "(#{contest.name} [#{link_to 'x', :action => 'remove_contest', :id => problem.id, :contest_id => contest.id }])" | |
|
100 | + - problem.tags.each do |t| | |
|
101 | + %span.label.label-default= t.name | |
|
102 | + %td= problem.available | |
|
103 | + %td= problem.date_added | |
|
104 | + - if GraderConfiguration.multicontests? | |
|
105 | + %td | |
|
106 | + - problem.contests.each do |contest| | |
|
107 | + = "(#{contest.name} [#{link_to 'x', :action => 'remove_contest', :id => problem.id, :contest_id => contest.id }])" | |
|
99 | 108 | |
|
100 | 109 | :javascript |
|
101 | 110 | $('.input-group.date').datetimepicker({ |
|
102 | 111 | format: 'DD/MMM/YYYY', |
|
103 | 112 | showTodayButton: true, |
|
104 | 113 | widgetPositioning: {horizontal: 'auto', vertical: 'bottom'}, |
|
105 | 114 | |
|
106 | 115 | }); |
|
107 | - | |
|
116 | + $('.datatable').DataTable({ | |
|
117 | + paging: false | |
|
118 | + }); |
@@ -1,35 +1,36 | |||
|
1 | 1 | %h1 Editing site |
|
2 | 2 | = error_messages_for :site |
|
3 | 3 | = form_for(@site) do |f| |
|
4 | 4 | .row |
|
5 | 5 | .col-md-4 |
|
6 | 6 | .form-group.field |
|
7 | 7 | = f.label :name, "Name" |
|
8 | 8 | = f.text_field :name, class: 'form-control' |
|
9 | 9 | .form-group.field |
|
10 | 10 | = f.label :password, "Password" |
|
11 | 11 | = f.text_field :password, class: 'form-control' |
|
12 | 12 | .form-group.field |
|
13 | 13 | = f.label :started, "Started" |
|
14 | 14 | = f.check_box :started, class: 'form-control' |
|
15 | 15 | .form-group.field |
|
16 | 16 | = f.label :start_time, "Start time" |
|
17 | 17 | -# = f.datetime_select :start_time, :include_blank => true |
|
18 | 18 | .input-group.date |
|
19 | 19 | = f.text_field :start_time, class:'form-control' , value: (@site.start_time ? @site.start_time.strftime('%d/%b/%Y %H:%M') : '') |
|
20 | 20 | %span.input-group-addon |
|
21 | 21 | %span.glyphicon.glyphicon-calendar |
|
22 | 22 | .actions |
|
23 | 23 | = f.submit "Update", class: 'btn btn-primary' |
|
24 | 24 | .col-md-8 |
|
25 | 25 | |
|
26 | 26 | = link_to 'Show', @site |
|
27 | 27 | | |
|
28 | 28 | = link_to 'Back', sites_path |
|
29 | 29 | |
|
30 | 30 | |
|
31 | 31 | :javascript |
|
32 | 32 | $('.input-group.date').datetimepicker({ |
|
33 | 33 | format: 'DD/MMM/YYYY HH:mm', |
|
34 | + showTodayButton: true, | |
|
34 | 35 | }); |
|
35 | 36 |
You need to be logged in to leave comments.
Login now