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

r876:8cd1c60e1ef0 - - The requested commit is too big and content was truncated. 22 files changed. Show full diff

@@ -0,0 +1,6
1 + %h1 New Problem
2 +
3 + = render 'form', problem: @problem
4 + .row.my-3
5 + .col-md-4
6 + = link_to 'Back', problems_path, class: 'btn btn-secondary'
@@ -0,0 +1,57
1 + # This migration comes from active_storage (originally 20170806125915)
2 + class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
3 + def change
4 + # Use Active Record's configured type for primary and foreign keys
5 + primary_key_type, foreign_key_type = primary_and_foreign_key_types
6 +
7 + create_table :active_storage_blobs, id: primary_key_type do |t|
8 + t.string :key, null: false
9 + t.string :filename, null: false
10 + t.string :content_type
11 + t.text :metadata
12 + t.string :service_name, null: false
13 + t.bigint :byte_size, null: false
14 + t.string :checksum
15 +
16 + if connection.supports_datetime_with_precision?
17 + t.datetime :created_at, precision: 6, null: false
18 + else
19 + t.datetime :created_at, null: false
20 + end
21 +
22 + t.index [ :key ], unique: true
23 + end
24 +
25 + create_table :active_storage_attachments, id: primary_key_type do |t|
26 + t.string :name, null: false
27 + t.references :record, null: false, polymorphic: true, index: false, type: foreign_key_type
28 + t.references :blob, null: false, type: foreign_key_type
29 +
30 + if connection.supports_datetime_with_precision?
31 + t.datetime :created_at, precision: 6, null: false
32 + else
33 + t.datetime :created_at, null: false
34 + end
35 +
36 + t.index [ :record_type, :record_id, :name, :blob_id ], name: :index_active_storage_attachments_uniqueness, unique: true
37 + t.foreign_key :active_storage_blobs, column: :blob_id
38 + end
39 +
40 + create_table :active_storage_variant_records, id: primary_key_type do |t|
41 + t.belongs_to :blob, null: false, index: false, type: foreign_key_type
42 + t.string :variation_digest, null: false
43 +
44 + t.index [ :blob_id, :variation_digest ], name: :index_active_storage_variant_records_uniqueness, unique: true
45 + t.foreign_key :active_storage_blobs, column: :blob_id
46 + end
47 + end
48 +
49 + private
50 + def primary_and_foreign_key_types
51 + config = Rails.configuration.generators
52 + setting = config.options[config.orm][:primary_key_type]
53 + primary_key_type = setting || :primary_key
54 + foreign_key_type = setting || :bigint
55 + [primary_key_type, foreign_key_type]
56 + end
57 + end
@@ -0,0 +1,6
1 + class AddDescriptionToProblems < ActiveRecord::Migration[7.0]
2 + def change
3 + add_column :problems, :description, :text
4 + add_column :problems, :markdown, :boolean
5 + end
6 + end
@@ -0,0 +1,21
1 + Problem.all.each do |p|
2 + next unless p.description_filename
3 + basename, ext = p.description_filename.split('.')
4 + filename = "#{Problem.download_file_basedir}/#{p.id}/#{basename}.#{ext}"
5 +
6 + if File.exists? filename
7 + p.statement.attach io: File.open(filename), filename: "#{basename}.#{ext}"
8 + puts "#{p.id}: OK"
9 + else
10 + puts "#{p.id}: #{p.name} #{filename} ERROR"
11 + end
12 +
13 + d = Description.where(id: p.description_id).first
14 + if d
15 + p.description = d.body
16 + p.markdown = d.markdowned
17 + end
18 + p.save
19 +
20 +
21 + end
@@ -35,3 +35,4
35 /config/secrets.yml
35 /config/secrets.yml
36
36
37 /.byebug_history
37 /.byebug_history
38 + /storage/*
@@ -77,7 +77,8
77 #gem 'jquery-datatables-rails'
77 #gem 'jquery-datatables-rails'
78
78
79 #----------- user interface -----------------
79 #----------- user interface -----------------
80 - gem 'simple_form'
80 + gem 'simple_form', git: 'https://github.com/heartcombo/simple_form', ref: '31fe255'
81 +
81 #select 2
82 #select 2
82 #gem 'select2-rails'
83 #gem 'select2-rails'
83 #ace editor
84 #ace editor
@@ -1,3 +1,12
1 + GIT
2 + remote: https://github.com/heartcombo/simple_form
3 + revision: 31fe25504771bd6cd425b585a4e0ed652fba4521
4 + ref: 31fe255
5 + specs:
6 + simple_form (5.1.0)
7 + actionpack (>= 5.2)
8 + activemodel (>= 5.2)
9 +
1 GIT
10 GIT
2 remote: https://github.com/mmotherwell/best_in_place
11 remote: https://github.com/mmotherwell/best_in_place
3 revision: 88eb3052623a9a6cd346864d2aca05021c2f80d0
12 revision: 88eb3052623a9a6cd346864d2aca05021c2f80d0
@@ -247,9 +256,6
247 rubyzip (>= 1.2.2, < 3.0)
256 rubyzip (>= 1.2.2, < 3.0)
248 websocket (~> 1.0)
257 websocket (~> 1.0)
249 sexp_processor (4.16.1)
258 sexp_processor (4.16.1)
250 - simple_form (5.1.0)
251 - actionpack (>= 5.2)
252 - activemodel (>= 5.2)
253 spring (2.1.1)
259 spring (2.1.1)
254 spring-watcher-listen (2.0.1)
260 spring-watcher-listen (2.0.1)
255 listen (>= 2.7, < 4.0)
261 listen (>= 2.7, < 4.0)
@@ -315,7 +321,7
315 rouge
321 rouge
316 sassc-rails
322 sassc-rails
317 selenium-webdriver
323 selenium-webdriver
318 - simple_form
324 + simple_form!
319 spring
325 spring
320 spring-watcher-listen (~> 2.0.0)
326 spring-watcher-listen (~> 2.0.0)
321 sprockets-rails
327 sprockets-rails
@@ -59,10 +59,6
59 }
59 }
60 }
60 }
61
61
62 - input {
63 - font-family: Tahoma, "sans-serif";
64 - }
65 -
66 h1 {
62 h1 {
67 color: #334488;
63 color: #334488;
68 }
64 }
@@ -7,6 +7,7
7 before_action :current_user
7 before_action :current_user
8 before_action :nav_announcement
8 before_action :nav_announcement
9 before_action :unique_visitor_id
9 before_action :unique_visitor_id
10 + before_action :active_controller_action
10
11
11 SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
12 SINGLE_USER_MODE_CONF_KEY = 'system.single_user_mode'
12 MULTIPLE_IP_LOGIN_CONF_KEY = 'right.multiple_ip_login'
13 MULTIPLE_IP_LOGIN_CONF_KEY = 'right.multiple_ip_login'
@@ -29,6 +30,12
29 @nav_announcement = Announcement.where(on_nav_bar: true)
30 @nav_announcement = Announcement.where(on_nav_bar: true)
30 end
31 end
31
32
33 + def active_controller_action
34 + #so that we can override this value inside each action
35 + @active_controller = controller_name
36 + @active_action = action_name
37 + end
38 +
32 def admin_authorization
39 def admin_authorization
33 return false unless check_valid_login
40 return false unless check_valid_login
34 user = User.includes(:roles).find(session[:user_id])
41 user = User.includes(:roles).find(session[:user_id])
@@ -1,38 +1,49
1 class ProblemsController < ApplicationController
1 class ProblemsController < ApplicationController
2
2
3 + include ActiveStorage::SetCurrent
4 +
3 before_action :admin_authorization, except: [:stat]
5 before_action :admin_authorization, except: [:stat]
6 + before_action :set_problem, only: [:show, :edit, :update, :destroy, :get_statement, :toggle, :toggle_test, :toggle_view_testcase, :stat]
4 before_action only: [:stat] do
7 before_action only: [:stat] do
5 authorization_by_roles(['admin','ta'])
8 authorization_by_roles(['admin','ta'])
6 end
9 end
7
10
11 +
8 def index
12 def index
9 @problems = Problem.order(date_added: :desc)
13 @problems = Problem.order(date_added: :desc)
10 end
14 end
11
15
12
16
13 def show
17 def show
14 - @problem = Problem.find(params[:id])
18 + end
19 +
20 + #get statement download link
21 + def get_statement
22 + unless @current_user.can_view_problem? @problem
23 + redirect_to list_main_path, error: 'You are not authorized to access this file'
24 + return
25 + end
26 +
27 + if params[:ext]=='pdf'
28 + content_type = 'application/pdf'
29 + else
30 + content_type = 'application/octet-stream'
31 + end
32 +
33 + filename = @problem.statement.filename.to_s
34 + data =@problem.statement.download
35 +
36 + send_data data, stream: false, disposition: 'inline', filename: filename, type: content_type
15 end
37 end
16
38
17 def new
39 def new
18 @problem = Problem.new
40 @problem = Problem.new
19 - @description = nil
20 end
41 end
21
42
22 def create
43 def create
23 @problem = Problem.new(problem_params)
44 @problem = Problem.new(problem_params)
24 - @description = Description.new(description_params)
25 - if @description.body!=''
26 - if !@description.save
27 - render :action => new and return
28 - end
29 - else
30 - @description = nil
31 - end
32 - @problem.description = @description
33 if @problem.save
45 if @problem.save
34 - flash[:notice] = 'Problem was successfully created.'
46 + redirect_to action: :index, notice: 'Problem was successfully created.'
35 - redirect_to action: :index
36 else
47 else
37 render :action => 'new'
48 render :action => 'new'
38 end
49 end
@@ -56,63 +67,31
56 end
67 end
57
68
58 def edit
69 def edit
59 - @problem = Problem.find(params[:id])
60 @description = @problem.description
70 @description = @problem.description
61 end
71 end
62
72
63 def update
73 def update
64 - @problem = Problem.find(params[:id])
74 + if problem_params[:statement] && problem_params[:statement].content_type != 'application/pdf'
65 - @description = @problem.description
75 + flash[:error] = 'Error: Uploaded file is not PDF'
66 - if @description.nil? and params[:description][:body]!=''
76 + render :action => 'edit'
67 - @description = Description.new(description_params)
77 + return
68 - if !@description.save
69 - flash[:notice] = 'Error saving description'
70 - render :action => 'edit' and return
71 - end
72 - @problem.description = @description
73 - elsif @description
74 - if !@description.update(description_params)
75 - flash[:notice] = 'Error saving description'
76 - render :action => 'edit' and return
77 - end
78 - end
79 - if params[:file] and params[:file].content_type != 'application/pdf'
80 - flash[:notice] = 'Error: Uploaded file is not PDF'
81 - render :action => 'edit' and return
82 end
78 end
83 if @problem.update(problem_params)
79 if @problem.update(problem_params)
84 - flash[:notice] = 'Problem was successfully updated.'
80 + flash[:notice] = 'Problem was successfully updated. '
85 - unless params[:file] == nil or params[:file] == ''
81 + flash[:notice] += 'A new statement PDF is uploaded' if problem_params[:statement]
86 - flash[:notice] = 'Problem was successfully updated and a new PDF file is uploaded.'
82 + @problem.save
87 - out_dirname = "#{Problem.download_file_basedir}/#{@problem.id}"
83 + redirect_to edit_problem_path(@problem)
88 - if not FileTest.exists? out_dirname
89 - Dir.mkdir out_dirname
90 - end
91 -
92 - out_filename = "#{out_dirname}/#{@problem.name}.pdf"
93 - if FileTest.exists? out_filename
94 - File.delete out_filename
95 - end
96 -
97 - File.open(out_filename,"wb") do |file|
98 - file.write(params[:file].read)
99 - end
100 - @problem.description_filename = "#{@problem.name}.pdf"
101 - @problem.save
102 - end
103 - redirect_to :action => 'show', :id => @problem
104 else
84 else
105 render :action => 'edit'
85 render :action => 'edit'
106 end
86 end
107 end
87 end
108
88
109 def destroy
89 def destroy
110 - p = Problem.find(params[:id]).destroy
90 + @problem.destroy
111 redirect_to action: :index
91 redirect_to action: :index
112 end
92 end
113
93
114 def toggle
94 def toggle
115 - @problem = Problem.find(params[:id])
116 @problem.update(available: !(@problem.available) )
95 @problem.update(available: !(@problem.available) )
117 respond_to do |format|
96 respond_to do |format|
118 format.js { }
97 format.js { }
@@ -120,7 +99,6
120 end
99 end
121
100
122 def toggle_test
101 def toggle_test
123 - @problem = Problem.find(params[:id])
124 @problem.update(test_allowed: !(@problem.test_allowed?) )
102 @problem.update(test_allowed: !(@problem.test_allowed?) )
125 respond_to do |format|
103 respond_to do |format|
126 format.js { }
104 format.js { }
@@ -128,7 +106,6
128 end
106 end
129
107
130 def toggle_view_testcase
108 def toggle_view_testcase
131 - @problem = Problem.find(params[:id])
132 @problem.update(view_testcase: !(@problem.view_testcase?) )
109 @problem.update(view_testcase: !(@problem.view_testcase?) )
133 respond_to do |format|
110 respond_to do |format|
134 format.js { }
111 format.js { }
@@ -152,7 +129,6
152 end
129 end
153
130
154 def stat
131 def stat
155 - @problem = Problem.find(params[:id])
156 unless @problem.available or session[:admin]
132 unless @problem.available or session[:admin]
157 redirect_to :controller => 'main', :action => 'list'
133 redirect_to :controller => 'main', :action => 'list'
158 return
134 return
@@ -295,8 +271,13
295
271
296 private
272 private
297
273
274 + def set_problem
275 + @problem = Problem.find(params[:id])
276 + end
277 +
298 def problem_params
278 def problem_params
299 - params.require(:problem).permit(:name, :full_name, :full_score, :change_date_added, :date_added, :available, :test_allowed,:output_only, :url, :description, tag_ids:[])
279 + params.require(:problem).permit(:name, :full_name, :full_score, :change_date_added, :date_added, :available,
280 + :test_allowed, :output_only, :url, :description, :statement, :description, tag_ids:[])
300 end
281 end
301
282
302 def description_params
283 def description_params
@@ -209,4 +209,15
209 BOOTSTRAP_FLASH_MSG.fetch(flash_type.to_sym, flash_type.to_s)
209 BOOTSTRAP_FLASH_MSG.fetch(flash_type.to_sym, flash_type.to_s)
210 end
210 end
211
211
212 + def active_class_when(options = {},cname = @active_controller, aname = @active_action)
213 + class_name = ' active '
214 + ok = true
215 + options.each do |k,v|
216 + ok = false if k == :controller && v.to_s != cname
217 + ok = false if k == :action && v.to_s != aname
218 + end
219 + return class_name if ok && options.size > 0
220 + return ''
221 + end
222 +
212 end
223 end
@@ -1,6 +1,7
1 class Problem < ApplicationRecord
1 class Problem < ApplicationRecord
2
2
3 - belongs_to :description
3 + #belongs_to :description
4 +
4 has_and_belongs_to_many :contests, :uniq => true
5 has_and_belongs_to_many :contests, :uniq => true
5
6
6 #has_and_belongs_to_many :groups
7 #has_and_belongs_to_many :groups
@@ -24,6 +25,9
24 DEFAULT_TIME_LIMIT = 1
25 DEFAULT_TIME_LIMIT = 1
25 DEFAULT_MEMORY_LIMIT = 32
26 DEFAULT_MEMORY_LIMIT = 32
26
27
28 + has_one_attached :statement
29 + has_many_attached :attachments
30 +
27 def get_jschart_history
31 def get_jschart_history
28 start = 4.month.ago.beginning_of_day
32 start = 4.month.ago.beginning_of_day
29 start_date = start.to_date
33 start_date = start.to_date
@@ -11,14 +11,14
11 / submission
11 / submission
12 - if (@current_user!=nil) and (GraderConfiguration.show_tasks_to?(@current_user))
12 - if (@current_user!=nil) and (GraderConfiguration.show_tasks_to?(@current_user))
13 %li.nav-item.dropdown.mx-2
13 %li.nav-item.dropdown.mx-2
14 - %a.nav-link.dropdown-toggle{href: '#', 'data-bs': {toggle:'dropdown'}, aria: {expanded:"false"}, role: "button"}
14 + %a.nav-link.dropdown-toggle.active-with-children{href: '#', 'data-bs': {toggle:'dropdown'}, aria: {expanded:"false"}, role: "button"}
15 = "#{I18n.t 'menu.submissions'}"
15 = "#{I18n.t 'menu.submissions'}"
16 %ul.dropdown-menu
16 %ul.dropdown-menu
17 - %li= link_to 'View', submissions_path, class:'dropdown-item'
17 + %li= link_to 'View', submissions_path, class: 'dropdown-item '+active_class_when(controller: :submissions)
18 %li= link_to 'Self Test', test_index_path, class:'dropdown-item'
18 %li= link_to 'Self Test', test_index_path, class:'dropdown-item'
19 / hall of fame
19 / hall of fame
20 - if GraderConfiguration['right.user_hall_of_fame']
20 - if GraderConfiguration['right.user_hall_of_fame']
21 - %li= link_to "#{I18n.t 'menu.hall_of_fame'}", problem_hof_report_path, class: 'nav-link mx-2'
21 + %li= link_to "#{I18n.t 'menu.hall_of_fame'}", problem_hof_report_path, class: 'nav-link mx-2'+active_class_when(controller: :report, action: :problem_hof)
22 / display MODE button (with countdown in contest mode)
22 / display MODE button (with countdown in contest mode)
23 - if GraderConfiguration.analysis_mode?
23 - if GraderConfiguration.analysis_mode?
24 %div.btn.btn-success#countdown= "ANALYSIS MODE"
24 %div.btn.btn-success#countdown= "ANALYSIS MODE"
@@ -35,33 +35,33
35 - if (@current_user!=nil) and (session[:admin])
35 - if (@current_user!=nil) and (session[:admin])
36 / management
36 / management
37 %li.nav-item.dropdown.mx-2
37 %li.nav-item.dropdown.mx-2
38 - %a.nav-link.dropdown-toggle{href: '#', 'data-bs': {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
38 + %a.nav-link.dropdown-toggle.active-with-children{href: '#', 'data-bs': {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
39 Manage
39 Manage
40 %ul.dropdown-menu
40 %ul.dropdown-menu
41 - %li= link_to 'Announcements', announcements_path, class: 'dropdown-item'
41 + %li= link_to 'Announcements', announcements_path, class: 'dropdown-item'+active_class_when(controller: :announcements)
42 - %li= link_to 'Problems', problems_path, class: 'dropdown-item'
42 + %li= link_to 'Problems', problems_path, class: 'dropdown-item'+active_class_when(controller: :problems)
43 - %li= link_to 'Tags', tags_path, class: 'dropdown-item'
43 + %li= link_to 'Tags', tags_path, class: 'dropdown-item'+active_class_when(controller: :tags)
44 - %li= link_to 'Users', user_admin_index_path, class: 'dropdown-item'
44 + %li= link_to 'Users', user_admin_index_path, class: 'dropdown-item'+active_class_when(controller: :user_admin)
45 - %li= link_to 'User Groups', groups_path, class: 'dropdown-item'
45 + %li= link_to 'User Groups', groups_path, class: 'dropdown-item'+active_class_when(controller: :groups)
46 - %li= link_to 'Graders', graders_list_path, class: 'dropdown-item'
46 + %li= link_to 'Graders', graders_list_path, class: 'dropdown-item'+active_class_when(controller: :graders)
47 - %li= link_to 'Message ', console_messages_path, class: 'dropdown-item'
47 + %li= link_to 'Message ', console_messages_path, class: 'dropdown-item'+active_class_when(controller: :messages)
48 %li
48 %li
49 %hr.dropdown-divider
49 %hr.dropdown-divider
50 - %li= link_to 'System config', grader_configuration_index_path, class: 'dropdown-item'
50 + %li= link_to 'System config', grader_configuration_index_path, class: 'dropdown-item'+active_class_when(controller: :grader_configuration)
51 %li
51 %li
52 %hr.dropdown-divider
52 %hr.dropdown-divider
53 - %li= link_to 'Sites', sites_path, class: 'dropdown-item'
53 + %li= link_to 'Sites', sites_path, class: 'dropdown-item'+active_class_when(controller: :sites)
54 - %li= link_to 'Contests', contest_management_index_path, class: 'dropdown-item'
54 + %li= link_to 'Contests', contest_management_index_path, class: 'dropdown-item'+active_class_when(controller: :contest_management)
55 -#
55 -#
56 / report
56 / report
57 %li.nav-item.dropdown.mx-2
57 %li.nav-item.dropdown.mx-2
58 - %a.nav-link.dropdown-toggle{href: '#', 'data-bs': {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
58 + %a.nav-link.dropdown-toggle.active-with-children{href: '#', 'data-bs': {toggle:'dropdown'}, aria: {haspopup:"true", expanded:"false"}, role: "button"}
59 Report
59 Report
60 %ul.dropdown-menu
60 %ul.dropdown-menu
61 - %li= link_to 'Current Score', current_score_report_path, class: 'dropdown-item'
61 + %li= link_to 'Current Score', current_score_report_path, class: 'dropdown-item'+active_class_when(controller: :report, action: :current_score)
62 - %li= link_to 'Score Report', max_score_report_path, class: 'dropdown-item'
62 + %li= link_to 'Score Report', max_score_report_path, class: 'dropdown-item'+active_class_when(controller: :report, action: :max_score)
63 - %li= link_to 'Submission Report', submission_report_path, class: 'dropdown-item'
63 + %li= link_to 'Submission Report', submission_report_path, class: 'dropdown-item'+active_class_when(controller: :report, action: :submission)
64 - %li= link_to 'Login Report', login_report_path, class: 'dropdown-item'
64 + %li= link_to 'Login Report', login_report_path, class: 'dropdown-item'+active_class_when(controller: :report, action: :login)
65 - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0
65 - if (ungraded = Submission.where('graded_at is null').where('submitted_at < ?', 1.minutes.ago).count) > 0
66 =link_to "#{ungraded} backlogs!",
66 =link_to "#{ungraded} backlogs!",
67 graders_list_path,
67 graders_list_path,
@@ -85,3 +85,9
85 %a.nav-link{href: login_main_path}
85 %a.nav-link{href: login_main_path}
86 %span.mi.mi-bs.md-18 exit_to_app
86 %span.mi.mi-bs.md-18 exit_to_app
87 = @current_user.full_name
87 = @current_user.full_name
88 + :javascript
89 + $('.active-with-children').each( (index,obj) => {
90 + if ($(obj).siblings('.dropdown-menu').has('.active').length > 0) {
91 + $(obj).addClass('active')
92 + }
93 + } )
@@ -1,55 +1,78
1 - = error_messages_for 'problem'
1 + = simple_form_for problem do |form|
2 - / [form:problem]
2 + .row
3 - .form-group
3 + .col-md-6
4 - %label{:for => "problem_name"} Name
4 + = form.input :name
5 - = text_field 'problem', 'name', class: 'form-control'
5 + = form.input :full_name
6 - %small
6 + = form.input :full_score
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.
7 + = form.input :tag_ids, collection: Tag.all, class: 'select2'
8 - .form-group
8 + = form.input :date_added
9 - %label{:for => "problem_full_name"} Full name
9 + = form.input :available
10 - = text_field 'problem', 'full_name', class: 'form-control'
10 + = form.input :test_allowed
11 - .form-group
11 + = form.input :output_only
12 - %label{:for => "problem_full_score"} Full score
12 + = form.input :description, as: :text
13 - = text_field 'problem', 'full_score', class: 'form-control'
13 + = form.input :markdown
14 - .form-group
14 + = form.input :url
15 - %label{:for => "problem_full_score"} Tags
15 + = form.input :statement
16 - = collection_select(:problem, :tag_ids, Tag.all, :id, :name, {}, {multiple: true, class: 'form-control select2'})
16 + %p
17 - .form-group
17 + - if @problem.statement.attached?
18 - %label{:for => "problem_date_added"} Date added
18 + %a{href: get_statement_problem_path(@problem)} [Download current Statement]
19 - = date_select 'problem', 'date_added', class: 'form-control'
19 + - else
20 - - # TODO: these should be put in model Problem, but I can't think of
20 + no statement attached to this problem
21 - - # nice default values for them. These values look fine only
21 + = form.submit :submit, class: 'btn btn-primary'
22 - - # in this case (of lazily adding new problems).
22 + -#
23 - - @problem.available = true if @problem!=nil and @problem.available==nil
23 + = error_messages_for 'problem'
24 - - @problem.test_allowed = true if @problem!=nil and @problem.test_allowed==nil
24 +
25 - - @problem.output_only = false if @problem!=nil and @problem.output_only==nil
25 + / [form:problem]
26 - .checkbox
26 + .form-group
27 - %label{:for => "problem_available"}
27 + %label{:for => "problem_name"} Name
28 - = check_box :problem, :available
28 + = text_field 'problem', 'name', class: 'form-control'
29 - Available?
29 + %small
30 - .checkbox
30 + 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.
31 - %label{:for => "problem_test_allowed"}
31 + .form-group
32 - = check_box :problem, :test_allowed
32 + %label{:for => "problem_full_name"} Full name
33 - Test allowed?
33 + = text_field 'problem', 'full_name', class: 'form-control'
34 - .checkbox
34 + .form-group
35 - %label{:for => "problem_output_only"}
35 + %label{:for => "problem_full_score"} Full score
36 - = check_box :problem, :output_only
36 + = text_field 'problem', 'full_score', class: 'form-control'
37 - Output only?
37 + .form-group
38 - = error_messages_for 'description'
38 + %label{:for => "problem_full_score"} Tags
39 - .form-group
39 + = collection_select(:problem, :tag_ids, Tag.all, :id, :name, {}, {multiple: true, class: 'form-control select2'})
40 - %label{:for => "description_body"} Description
40 + .form-group
41 - %br/
41 + %label{:for => "problem_date_added"} Date added
42 - = text_area :description, :body, :rows => 10, :cols => 80,class: 'form-control'
42 + = date_select 'problem', 'date_added', class: 'form-control'
43 - .form-group
43 + - # TODO: these should be put in model Problem, but I can't think of
44 - %label{:for => "description_markdowned"} Markdowned?
44 + - # nice default values for them. These values look fine only
45 - = select "description", |
45 + - # in this case (of lazily adding new problems).
46 - "markdowned", |
46 + - @problem.available = true if @problem!=nil and @problem.available==nil
47 - [['True',true],['False',false]], |
47 + - @problem.test_allowed = true if @problem!=nil and @problem.test_allowed==nil
48 - {:selected => (@description) ? @description.markdowned : false } |
48 + - @problem.output_only = false if @problem!=nil and @problem.output_only==nil
49 - .form-group
49 + .checkbox
50 - %label{:for => "problem_url"} URL
50 + %label{:for => "problem_available"}
51 - %br/
51 + = check_box :problem, :available
52 - = text_field 'problem', 'url',class: 'form-control'
52 + Available?
53 - %p
53 + .checkbox
54 - Task PDF #{file_field_tag 'file'}
54 + %label{:for => "problem_test_allowed"}
55 - / [eoform:problem]
55 + = check_box :problem, :test_allowed
56 + Test allowed?
57 + .checkbox
58 + %label{:for => "problem_output_only"}
59 + = check_box :problem, :output_only
60 + Output only?
61 + = error_messages_for 'description'
62 + .form-group
63 + %label{:for => "description_body"} Description
64 + %br/
65 + = text_area :description, :body, :rows => 10, :cols => 80,class: 'form-control'
66 + .form-group
67 + %label{:for => "description_markdowned"} Markdowned?
68 + = select "description", |
69 + "markdowned", |
70 + [['True',true],['False',false]], |
71 + {:selected => (@description) ? @description.markdowned : false } |
72 + .form-group
73 + %label{:for => "problem_url"} URL
74 + %br/
75 + = text_field 'problem', 'url',class: 'form-control'
76 + %p
77 + Task PDF #{file_field_tag 'file'}
78 + / [eoform:problem]
@@ -1,14 +1,6
1 - .container-fluid
1 + %h1 Editing Problem
2 - = form_for @problem,url:{action: 'update'},html: {multipart: true} do
2 +
3 - .row
3 + = render 'form', problem: @problem
4 - .col-md-6
4 + .row.my-3
5 - %h1 Editing problem
5 + .col-md-4
6 - = render :partial => 'form'
6 + = link_to 'Back', problems_path, class: 'btn btn-secondary'
7 - .row
8 - .col-md-4
9 - = submit_tag 'Edit', class: 'btn btn-primary btn-block'
10 - .col-md-4
11 - = link_to 'Show', {:action => 'show', :id => @problem}, class: 'btn btn-default btn-block'
12 - .col-md-4
13 - = link_to 'Back', problems_path, class: 'btn btn-default btn-block'
14 - .div{style: 'height: 5em'}
@@ -37,6 +37,9
37 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user uses test interface on this problem?' } [?]
37 %sup{class: 'text-primary',data: {toggle: 'tooltip'}, title: 'Let user uses test interface on this problem?' } [?]
38 - if GraderConfiguration.multicontests?
38 - if GraderConfiguration.multicontests?
39 %th Contests
39 %th Contests
40 + %th.text-center
41 + %th.text-center
42 + %th.text-center
40 - for problem in @problems
43 - for problem in @problems
41 %tr{:class => "#{(problem.available) ? "bg-success bg-opacity-25" : "bg-opacity-25"}", :id => "prob-#{problem.id}", :name => "prob-#{problem.id}"}
44 %tr{:class => "#{(problem.available) ? "bg-success bg-opacity-25" : "bg-opacity-25"}", :id => "prob-#{problem.id}", :name => "prob-#{problem.id}"}
42 - @problem=problem
45 - @problem=problem
@@ -58,7 +61,6
58 %td
61 %td
59 = problem.contests.collect { |c| c.name }.join(', ')
62 = problem.contests.collect { |c| c.name }.join(', ')
60 %td= link_to 'Stat', {:action => 'stat', :id => problem.id}, class: 'btn btn-info btn-sm btn-block'
63 %td= link_to 'Stat', {:action => 'stat', :id => problem.id}, class: 'btn btn-info btn-sm btn-block'
61 - %td= link_to 'Show', {:action => 'show', :id => problem}, class: 'btn btn-info btn-sm btn-block'
62 %td= link_to 'Edit', {:action => 'edit', :id => problem}, class: 'btn btn-info btn-sm btn-block'
64 %td= link_to 'Edit', {:action => 'edit', :id => problem}, class: 'btn btn-info btn-sm btn-block'
63 %td= link_to 'Destroy', { :action => 'destroy', :id => problem }, :confirm => 'Are you sure?', :method => :delete, class: 'btn btn-danger btn-sm btn-block'
65 %td= link_to 'Destroy', { :action => 'destroy', :id => problem }, :confirm => 'Are you sure?', :method => :delete, class: 'btn btn-danger btn-sm btn-block'
64 %br/
66 %br/
@@ -112,7 +112,7
112 # You can define the class to use on all labels. Default is nil.
112 # You can define the class to use on all labels. Default is nil.
113 # config.label_class = nil
113 # config.label_class = nil
114
114
115 - # You can define the default class to be used on forms. Can be overriden
115 + # You can define the default class to be used on forms. Can be overridden
116 # with `html: { :class }`. Defaulting to none.
116 # with `html: { :class }`. Defaulting to none.
117 # config.default_form_class = nil
117 # config.default_form_class = nil
118
118
@@ -1,10 +1,8
1 # frozen_string_literal: true
1 # frozen_string_literal: true
2
2
3 - # Please do not make direct changes to this file!
3 + # These defaults are defined and maintained by the community at
4 - # This generator is maintained by the community around simple_form-bootstrap:
4 + # https://github.com/heartcombo/simple_form-bootstrap
5 - # https://github.com/rafaelfranca/simple_form-bootstrap
5 + # Please submit feedback, changes and tests only there.
6 - # All future development, tests, and organization should happen there.
7 - # Background history: https://github.com/heartcombo/simple_form/issues/1561
8
6
9 # Uncomment this and change the path if necessary to include your own
7 # Uncomment this and change the path if necessary to include your own
10 # components.
8 # components.
@@ -43,13 +41,13
43
41
44 # add validation classes to `input_field`
42 # add validation classes to `input_field`
45 config.input_field_error_class = 'is-invalid'
43 config.input_field_error_class = 'is-invalid'
46 - config.input_field_valid_class = 'is-valid'
44 + config.input_field_valid_class = 'is-valid-xxx'
47
45
48
46
49 # vertical forms
47 # vertical forms
50 #
48 #
51 # vertical default_wrapper
49 # vertical default_wrapper
52 - config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
50 + config.wrappers :vertical_form, class: 'mb-3' do |b|
53 b.use :html5
51 b.use :html5
54 b.use :placeholder
52 b.use :placeholder
55 b.optional :maxlength
53 b.optional :maxlength
@@ -57,90 +55,100
57 b.optional :pattern
55 b.optional :pattern
58 b.optional :min_max
56 b.optional :min_max
59 b.optional :readonly
57 b.optional :readonly
60 - b.use :label
58 + b.use :label, class: 'form-label'
61 - b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
59 + b.use :input, class: 'form-control', error_class: 'is-invalid'
62 - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
60 + b.use :full_error, wrap_with: { class: 'invalid-feedback' }
63 - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
61 + b.use :hint, wrap_with: { class: 'form-text' }
64 end
62 end
65
63
66 # vertical input for boolean
64 # vertical input for boolean
67 - config.wrappers :vertical_boolean, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
65 + config.wrappers :vertical_boolean, tag: 'fieldset', class: 'mb-3' do |b|
68 b.use :html5
66 b.use :html5
69 b.optional :readonly
67 b.optional :readonly
70 - b.wrapper :form_check_wrapper, tag: 'div', class: 'form-check' do |bb|
68 + b.wrapper :form_check_wrapper, class: 'form-check' do |bb|
71 - bb.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
69 + bb.use :input, class: 'form-check-input', error_class: 'is-invalid'
72 bb.use :label, class: 'form-check-label'
70 bb.use :label, class: 'form-check-label'
73 - bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
71 + bb.use :full_error, wrap_with: { class: 'invalid-feedback' }
74 - bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
72 + bb.use :hint, wrap_with: { class: 'form-text' }
75 end
73 end
76 end
74 end
77
75
78 # vertical input for radio buttons and check boxes
76 # vertical input for radio buttons and check boxes
79 - config.wrappers :vertical_collection, item_wrapper_class: 'form-check', item_label_class: 'form-check-label', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
77 + config.wrappers :vertical_collection, item_wrapper_class: 'form-check', item_label_class: 'form-check-label', tag: 'fieldset', class: 'mb-3' do |b|
80 b.use :html5
78 b.use :html5
81 b.optional :readonly
79 b.optional :readonly
82 b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
80 b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
83 ba.use :label_text
81 ba.use :label_text
84 end
82 end
85 - b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
83 + b.use :input, class: 'form-check-input', error_class: 'is-invalid'
86 - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
84 + b.use :full_error, wrap_with: { class: 'invalid-feedback d-block' }
87 - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
85 + b.use :hint, wrap_with: { class: 'form-text' }
88 end
86 end
89
87
90 # vertical input for inline radio buttons and check boxes
88 # vertical input for inline radio buttons and check boxes
91 - config.wrappers :vertical_collection_inline, item_wrapper_class: 'form-check form-check-inline', item_label_class: 'form-check-label', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
89 + config.wrappers :vertical_collection_inline, item_wrapper_class: 'form-check form-check-inline', item_label_class: 'form-check-label', tag: 'fieldset', class: 'mb-3' do |b|
92 b.use :html5
90 b.use :html5
93 b.optional :readonly
91 b.optional :readonly
94 b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
92 b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
95 ba.use :label_text
93 ba.use :label_text
96 end
94 end
97 - b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
95 + b.use :input, class: 'form-check-input', error_class: 'is-invalid'
98 - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
96 + b.use :full_error, wrap_with: { class: 'invalid-feedback d-block' }
99 - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
97 + b.use :hint, wrap_with: { class: 'form-text' }
100 end
98 end
101
99
102 # vertical file input
100 # vertical file input
103 - config.wrappers :vertical_file, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
101 + config.wrappers :vertical_file, class: 'mb-3' do |b|
104 b.use :html5
102 b.use :html5
105 b.use :placeholder
103 b.use :placeholder
106 b.optional :maxlength
104 b.optional :maxlength
107 b.optional :minlength
105 b.optional :minlength
108 b.optional :readonly
106 b.optional :readonly
109 - b.use :label
107 + b.use :label, class: 'form-label'
110 - b.use :input, class: 'form-control-file', error_class: 'is-invalid', valid_class: 'is-valid'
108 + b.use :input, class: 'form-control', error_class: 'is-invalid'
111 - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
109 + b.use :full_error, wrap_with: { class: 'invalid-feedback' }
112 - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
110 + b.use :hint, wrap_with: { class: 'form-text' }
111 + end
112 +
113 + # vertical select input
114 + config.wrappers :vertical_select, class: 'mb-3' do |b|
115 + b.use :html5
116 + b.optional :readonly
117 + b.use :label, class: 'form-label'
118 + b.use :input, class: 'form-select', error_class: 'is-invalid'
119 + b.use :full_error, wrap_with: { class: 'invalid-feedback' }
120 + b.use :hint, wrap_with: { class: 'form-text' }
113 end
121 end
114
122
115 # vertical multi select
123 # vertical multi select
116 - config.wrappers :vertical_multi_select, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
124 + config.wrappers :vertical_multi_select, class: 'mb-3' do |b|
117 b.use :html5
125 b.use :html5
118 b.optional :readonly
126 b.optional :readonly
119 - b.use :label
127 + b.use :label, class: 'form-label'
120 - b.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |ba|
128 + b.wrapper class: 'd-flex flex-row justify-content-between align-items-center' do |ba|
121 - ba.use :input, class: 'form-control mx-1', error_class: 'is-invalid', valid_class: 'is-valid'
129 + ba.use :input, class: 'form-select mx-1', error_class: 'is-invalid'
122 end
130 end
123 - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
131 + b.use :full_error, wrap_with: { class: 'invalid-feedback d-block' }
124 - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
132 + b.use :hint, wrap_with: { class: 'form-text' }
125 end
133 end
126
134
127 # vertical range input
135 # vertical range input
128 - config.wrappers :vertical_range, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
136 + config.wrappers :vertical_range, class: 'mb-3' do |b|
129 b.use :html5
137 b.use :html5
130 b.use :placeholder
138 b.use :placeholder
131 b.optional :readonly
139 b.optional :readonly
132 b.optional :step
140 b.optional :step
133 - b.use :label
141 + b.use :label, class: 'form-label'
134 - b.use :input, class: 'form-control-range', error_class: 'is-invalid', valid_class: 'is-valid'
142 + b.use :input, class: 'form-range', error_class: 'is-invalid'
135 - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
143 + b.use :full_error, wrap_with: { class: 'invalid-feedback' }
136 - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
144 + b.use :hint, wrap_with: { class: 'form-text' }
137 end
145 end
138
146
139
147
140 # horizontal forms
148 # horizontal forms
141 #
149 #
142 # horizontal default_wrapper
150 # horizontal default_wrapper
143 - config.wrappers :horizontal_form, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
151 + config.wrappers :horizontal_form, class: 'row mb-3' do |b|
144 b.use :html5
152 b.use :html5
145 b.use :placeholder
153 b.use :placeholder
146 b.optional :maxlength
154 b.optional :maxlength
@@ -149,94 +157,103
149 b.optional :min_max
157 b.optional :min_max
150 b.optional :readonly
158 b.optional :readonly
151 b.use :label, class: 'col-sm-3 col-form-label'
159 b.use :label, class: 'col-sm-3 col-form-label'
152 - b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
160 + b.wrapper :grid_wrapper, class: 'col-sm-9' do |ba|
153 - ba.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
161 + ba.use :input, class: 'form-control', error_class: 'is-invalid'
154 - ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
162 + ba.use :full_error, wrap_with: { class: 'invalid-feedback' }
155 - ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
163 + ba.use :hint, wrap_with: { class: 'form-text' }
156 end
164 end
157 end
165 end
158
166
159 # horizontal input for boolean
167 # horizontal input for boolean
160 - config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
168 + config.wrappers :horizontal_boolean, class: 'row mb-3' do |b|
161 b.use :html5
169 b.use :html5
162 b.optional :readonly
170 b.optional :readonly
163 - b.wrapper tag: 'label', class: 'col-sm-3' do |ba|
171 + b.wrapper :grid_wrapper, class: 'col-sm-9 offset-sm-3' do |wr|
164 - ba.use :label_text
172 + wr.wrapper :form_check_wrapper, class: 'form-check' do |bb|
165 - end
173 + bb.use :input, class: 'form-check-input', error_class: 'is-invalid'
166 - b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |wr|
167 - wr.wrapper :form_check_wrapper, tag: 'div', class: 'form-check' do |bb|
168 - bb.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
169 bb.use :label, class: 'form-check-label'
174 bb.use :label, class: 'form-check-label'
170 - bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
175 + bb.use :full_error, wrap_with: { class: 'invalid-feedback' }
171 - bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
176 + bb.use :hint, wrap_with: { class: 'form-text' }
172 end
177 end
173 end
178 end
174 end
179 end
175
180
176 # horizontal input for radio buttons and check boxes
181 # horizontal input for radio buttons and check boxes
177 - config.wrappers :horizontal_collection, item_wrapper_class: 'form-check', item_label_class: 'form-check-label', tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
182 + config.wrappers :horizontal_collection, item_wrapper_class: 'form-check', item_label_class: 'form-check-label', class: 'row mb-3' do |b|
178 b.use :html5
183 b.use :html5
179 b.optional :readonly
184 b.optional :readonly
180 b.use :label, class: 'col-sm-3 col-form-label pt-0'
185 b.use :label, class: 'col-sm-3 col-form-label pt-0'
181 - b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
186 + b.wrapper :grid_wrapper, class: 'col-sm-9' do |ba|
182 - ba.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
187 + ba.use :input, class: 'form-check-input', error_class: 'is-invalid'
183 - ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
188 + ba.use :full_error, wrap_with: { class: 'invalid-feedback d-block' }
184 - ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
189 + ba.use :hint, wrap_with: { class: 'form-text' }
185 end
190 end
186 end
191 end
187
192
188 # horizontal input for inline radio buttons and check boxes
193 # horizontal input for inline radio buttons and check boxes
189 - config.wrappers :horizontal_collection_inline, item_wrapper_class: 'form-check form-check-inline', item_label_class: 'form-check-label', tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
194 + config.wrappers :horizontal_collection_inline, item_wrapper_class: 'form-check form-check-inline', item_label_class: 'form-check-label', class: 'row mb-3' do |b|
190 b.use :html5
195 b.use :html5
191 b.optional :readonly
196 b.optional :readonly
192 b.use :label, class: 'col-sm-3 col-form-label pt-0'
197 b.use :label, class: 'col-sm-3 col-form-label pt-0'
193 - b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
198 + b.wrapper :grid_wrapper, class: 'col-sm-9' do |ba|
194 - ba.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
199 + ba.use :input, class: 'form-check-input', error_class: 'is-invalid'
195 - ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
200 + ba.use :full_error, wrap_with: { class: 'invalid-feedback d-block' }
196 - ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
201 + ba.use :hint, wrap_with: { class: 'form-text' }
197 end
202 end
198 end
203 end
199
204
200 # horizontal file input
205 # horizontal file input
201 - config.wrappers :horizontal_file, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
206 + config.wrappers :horizontal_file, class: 'row mb-3' do |b|
202 b.use :html5
207 b.use :html5
203 b.use :placeholder
208 b.use :placeholder
204 b.optional :maxlength
209 b.optional :maxlength
205 b.optional :minlength
210 b.optional :minlength
206 b.optional :readonly
211 b.optional :readonly
207 b.use :label, class: 'col-sm-3 col-form-label'
212 b.use :label, class: 'col-sm-3 col-form-label'
208 - b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
213 + b.wrapper :grid_wrapper, class: 'col-sm-9' do |ba|
209 - ba.use :input, error_class: 'is-invalid', valid_class: 'is-valid'
214 + ba.use :input, class: 'form-control', error_class: 'is-invalid'
210 - ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
215 + ba.use :full_error, wrap_with: { class: 'invalid-feedback' }
211 - ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
216 + ba.use :hint, wrap_with: { class: 'form-text' }
217 + end
218 + end
219 +
220 + # horizontal select input
221 + config.wrappers :horizontal_select, class: 'row mb-3' do |b|
222 + b.use :html5
223 + b.optional :readonly
224 + b.use :label, class: 'col-sm-3 col-form-label'
225 + b.wrapper :grid_wrapper, class: 'col-sm-9' do |ba|
226 + ba.use :input, class: 'form-select', error_class: 'is-invalid'
227 + ba.use :full_error, wrap_with: { class: 'invalid-feedback' }
228 + ba.use :hint, wrap_with: { class: 'form-text' }
212 end
229 end
213 end
230 end
214
231
215 # horizontal multi select
232 # horizontal multi select
216 - config.wrappers :horizontal_multi_select, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
233 + config.wrappers :horizontal_multi_select, class: 'row mb-3' do |b|
217 b.use :html5
234 b.use :html5
218 b.optional :readonly
235 b.optional :readonly
219 b.use :label, class: 'col-sm-3 col-form-label'
236 b.use :label, class: 'col-sm-3 col-form-label'
220 - b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
237 + b.wrapper :grid_wrapper, class: 'col-sm-9' do |ba|
221 - ba.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |bb|
238 + ba.wrapper class: 'd-flex flex-row justify-content-between align-items-center' do |bb|
222 - bb.use :input, class: 'form-control mx-1', error_class: 'is-invalid', valid_class: 'is-valid'
239 + bb.use :input, class: 'form-select mx-1', error_class: 'is-invalid'
223 end
240 end
224 - ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
241 + ba.use :full_error, wrap_with: { class: 'invalid-feedback d-block' }
225 - ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
242 + ba.use :hint, wrap_with: { class: 'form-text' }
226 end
243 end
227 end
244 end
228
245
229 # horizontal range input
246 # horizontal range input
230 - config.wrappers :horizontal_range, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
247 + config.wrappers :horizontal_range, class: 'row mb-3' do |b|
231 b.use :html5
248 b.use :html5
232 b.use :placeholder
249 b.use :placeholder
233 b.optional :readonly
250 b.optional :readonly
234 b.optional :step
251 b.optional :step
235 - b.use :label, class: 'col-sm-3 col-form-label'
252 + b.use :label, class: 'col-sm-3 col-form-label pt-0'
236 - b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
253 + b.wrapper :grid_wrapper, class: 'col-sm-9' do |ba|
237 - ba.use :input, class: 'form-control-range', error_class: 'is-invalid', valid_class: 'is-valid'
254 + ba.use :input, class: 'form-range', error_class: 'is-invalid'
238 - ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
255 + ba.use :full_error, wrap_with: { class: 'invalid-feedback' }
239 - ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
256 + ba.use :hint, wrap_with: { class: 'form-text' }
240 end
257 end
241 end
258 end
242
259
@@ -244,7 +261,7
244 # inline forms
261 # inline forms
245 #
262 #
246 # inline default_wrapper
263 # inline default_wrapper
247 - config.wrappers :inline_form, tag: 'span', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
264 + config.wrappers :inline_form, class: 'col-12' do |b|
248 b.use :html5
265 b.use :html5
249 b.use :placeholder
266 b.use :placeholder
250 b.optional :maxlength
267 b.optional :maxlength
@@ -252,140 +269,44
252 b.optional :pattern
269 b.optional :pattern
253 b.optional :min_max
270 b.optional :min_max
254 b.optional :readonly
271 b.optional :readonly
255 - b.use :label, class: 'sr-only'
272 + b.use :label, class: 'visually-hidden'
256
273
257 - b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
274 + b.use :input, class: 'form-control', error_class: 'is-invalid'
258 - b.use :error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
275 + b.use :error, wrap_with: { class: 'invalid-feedback' }
259 - b.optional :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
276 + b.optional :hint, wrap_with: { class: 'form-text' }
260 end
277 end
261
278
262 # inline input for boolean
279 # inline input for boolean
263 - config.wrappers :inline_boolean, tag: 'span', class: 'form-check mb-2 mr-sm-2', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
280 + config.wrappers :inline_boolean, class: 'col-12' do |b|
264 b.use :html5
281 b.use :html5
265 b.optional :readonly
282 b.optional :readonly
266 - b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
283 + b.wrapper :form_check_wrapper, class: 'form-check' do |bb|
267 - b.use :label, class: 'form-check-label'
284 + bb.use :input, class: 'form-check-input', error_class: 'is-invalid'
268 - b.use :error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
285 + bb.use :label, class: 'form-check-label'
269 - b.optional :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
286 + bb.use :error, wrap_with: { class: 'invalid-feedback' }
287 + bb.optional :hint, wrap_with: { class: 'form-text' }
288 + end
270 end
289 end
271
290
272
291
273 # bootstrap custom forms
292 # bootstrap custom forms
274 #
293 #
275 - # custom input for boolean
276 - config.wrappers :custom_boolean, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
277 - b.use :html5
278 - b.optional :readonly
279 - b.wrapper :form_check_wrapper, tag: 'div', class: 'custom-control custom-checkbox' do |bb|
280 - bb.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
281 - bb.use :label, class: 'custom-control-label'
282 - bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
283 - bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
284 - end
285 - end
286 -
287 # custom input switch for boolean
294 # custom input switch for boolean
288 - config.wrappers :custom_boolean_switch, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
295 + config.wrappers :custom_boolean_switch, class: 'mb-3' do |b|
289 - b.use :html5
290 - b.optional :readonly
291 - b.wrapper :form_check_wrapper, tag: 'div', class: 'custom-control custom-switch' do |bb|
292 - bb.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
293 - bb.use :label, class: 'custom-control-label'
294 - bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
295 - bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
296 - end
297 - end
298 -
299 - # custom input for radio buttons and check boxes
300 - config.wrappers :custom_collection, item_wrapper_class: 'custom-control', item_label_class: 'custom-control-label', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
301 - b.use :html5
302 - b.optional :readonly
303 - b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
304 - ba.use :label_text
305 - end
306 - b.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
307 - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
308 - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
309 - end
310 -
311 - # custom input for inline radio buttons and check boxes
312 - config.wrappers :custom_collection_inline, item_wrapper_class: 'custom-control custom-control-inline', item_label_class: 'custom-control-label', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
313 b.use :html5
296 b.use :html5
314 b.optional :readonly
297 b.optional :readonly
315 - b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
298 + b.wrapper :form_check_wrapper, tag: 'div', class: 'form-check form-switch' do |bb|
316 - ba.use :label_text
299 + bb.use :input, class: 'form-check-input', error_class: 'is-invalid'
317 - end
300 + bb.use :label, class: 'form-check-label'
318 - b.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
301 + bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
319 - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
302 + bb.use :hint, wrap_with: { class: 'form-text' }
320 - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
321 - end
322 -
323 - # custom file input
324 - config.wrappers :custom_file, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
325 - b.use :html5
326 - b.use :placeholder
327 - b.optional :maxlength
328 - b.optional :minlength
329 - b.optional :readonly
330 - b.use :label
331 - b.wrapper :custom_file_wrapper, tag: 'div', class: 'custom-file' do |ba|
332 - ba.use :input, class: 'custom-file-input', error_class: 'is-invalid', valid_class: 'is-valid'
333 - ba.use :label, class: 'custom-file-label'
334 - ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
335 end
303 end
336 - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
337 - end
338 -
339 - # custom multi select
340 - config.wrappers :custom_multi_select, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
341 - b.use :html5
342 - b.optional :readonly
343 - b.use :label
344 - b.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |ba|
345 - ba.use :input, class: 'custom-select mx-1', error_class: 'is-invalid', valid_class: 'is-valid'
346 - end
347 - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
348 - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
349 - end
350 -
351 - # custom range input
352 - config.wrappers :custom_range, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
353 - b.use :html5
354 - b.use :placeholder
355 - b.optional :readonly
356 - b.optional :step
357 - b.use :label
358 - b.use :input, class: 'custom-range', error_class: 'is-invalid', valid_class: 'is-valid'
359 - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
360 - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
361 end
304 end
362
305
363
306
364 # Input Group - custom component
307 # Input Group - custom component
365 - # see example app and config at https://github.com/rafaelfranca/simple_form-bootstrap
308 + # see example app and config at https://github.com/heartcombo/simple_form-bootstrap
366 - # config.wrappers :input_group, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
309 + config.wrappers :input_group, class: 'mb-3' do |b|
367 - # b.use :html5
368 - # b.use :placeholder
369 - # b.optional :maxlength
370 - # b.optional :minlength
371 - # b.optional :pattern
372 - # b.optional :min_max
373 - # b.optional :readonly
374 - # b.use :label
375 - # b.wrapper :input_group_tag, tag: 'div', class: 'input-group' do |ba|
376 - # ba.optional :prepend
377 - # ba.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
378 - # ba.optional :append
379 - # end
380 - # b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
381 - # b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
382 - # end
383 -
384 -
385 - # Floating Labels form
386 - #
387 - # floating labels default_wrapper
388 - config.wrappers :floating_labels_form, tag: 'div', class: 'form-label-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
389 b.use :html5
310 b.use :html5
390 b.use :placeholder
311 b.use :placeholder
391 b.optional :maxlength
312 b.optional :maxlength
@@ -393,20 +314,42
393 b.optional :pattern
314 b.optional :pattern
394 b.optional :min_max
315 b.optional :min_max
395 b.optional :readonly
316 b.optional :readonly
396 - b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
317 + b.use :label, class: 'form-label'
318 + b.wrapper :input_group_tag, class: 'input-group' do |ba|
319 + ba.optional :prepend
320 + ba.use :input, class: 'form-control', error_class: 'is-invalid'
321 + ba.optional :append
322 + ba.use :full_error, wrap_with: { class: 'invalid-feedback' }
323 + end
324 + b.use :hint, wrap_with: { class: 'form-text' }
325 + end
326 +
327 +
328 + # Floating Labels form
329 + #
330 + # floating labels default_wrapper
331 + config.wrappers :floating_labels_form, class: 'form-floating mb-3' do |b|
332 + b.use :html5
333 + b.use :placeholder
334 + b.optional :maxlength
335 + b.optional :minlength
336 + b.optional :pattern
337 + b.optional :min_max
338 + b.optional :readonly
339 + b.use :input, class: 'form-control', error_class: 'is-invalid'
397 b.use :label
340 b.use :label
398 - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
341 + b.use :full_error, wrap_with: { class: 'invalid-feedback' }
399 - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
342 + b.use :hint, wrap_with: { class: 'form-text' }
400 end
343 end
401
344
402 # custom multi select
345 # custom multi select
403 - config.wrappers :floating_labels_select, tag: 'div', class: 'form-label-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
346 + config.wrappers :floating_labels_select, class: 'form-floating mb-3' do |b|
404 b.use :html5
347 b.use :html5
405 b.optional :readonly
348 b.optional :readonly
406 - b.use :input, class: 'custom-select', error_class: 'is-invalid', valid_class: 'is-valid'
349 + b.use :input, class: 'form-select', error_class: 'is-invalid'
407 b.use :label
350 b.use :label
408 - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
351 + b.use :full_error, wrap_with: { class: 'invalid-feedback' }
409 - b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
352 + b.use :hint, wrap_with: { class: 'form-text' }
410 end
353 end
411
354
412
355
@@ -423,18 +366,7
423 file: :vertical_file,
366 file: :vertical_file,
424 radio_buttons: :vertical_collection,
367 radio_buttons: :vertical_collection,
425 range: :vertical_range,
368 range: :vertical_range,
426 - time: :vertical_multi_select
369 + time: :vertical_multi_select,
370 + select: :vertical_select
427 }
371 }
428 -
429 - # enable custom form wrappers
430 - # config.wrapper_mappings = {
431 - # boolean: :custom_boolean,
432 - # check_boxes: :custom_collection,
433 - # date: :custom_multi_select,
434 - # datetime: :custom_multi_select,
435 - # file: :custom_file,
436 - # radio_buttons: :custom_collection,
437 - # range: :custom_range,
438 - # time: :custom_multi_select
439 - # }
440 end
372 end
@@ -34,6 +34,7
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 + get 'get_statement'
37 end
38 end
38 collection do
39 collection do
39 get 'turn_all_off'
40 get 'turn_all_off'
@@ -10,10 +10,38
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[7.0].define(version: 2022_02_04_080936) do
13 + ActiveRecord::Schema[7.0].define(version: 2022_09_27_074644) do
14 - create_table "announcements", id: :integer, charset: "utf8", force: :cascade do |t|
14 + create_table "active_storage_attachments", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
15 + t.string "name", null: false
16 + t.string "record_type", null: false
17 + t.bigint "record_id", null: false
18 + t.bigint "blob_id", null: false
19 + t.datetime "created_at", null: false
20 + t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id"
21 + t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true
22 + end
23 +
24 + create_table "active_storage_blobs", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
25 + t.string "key", null: false
26 + t.string "filename", null: false
27 + t.string "content_type"
28 + t.text "metadata"
29 + t.string "service_name", null: false
30 + t.bigint "byte_size", null: false
31 + t.string "checksum"
32 + t.datetime "created_at", null: false
33 + t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true
34 + end
35 +
36 + create_table "active_storage_variant_records", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
37 + t.bigint "blob_id", null: false
38 + t.string "variation_digest", null: false
39 + t.index ["blob_id", "variation_digest"], name: "index_active_storage_variant_records_uniqueness", unique: true
40 + end
41 +
42 + create_table "announcements", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
15 t.string "author"
43 t.string "author"
16 - t.text "body", size: :medium
44 + t.text "body"
17 t.boolean "published"
45 t.boolean "published"
18 t.datetime "created_at", precision: nil, null: false
46 t.datetime "created_at", precision: nil, null: false
19 t.datetime "updated_at", precision: nil, null: false
47 t.datetime "updated_at", precision: nil, null: false
@@ -24,7 +52,7
24 t.boolean "on_nav_bar", default: false
52 t.boolean "on_nav_bar", default: false
25 end
53 end
26
54
27 - create_table "contests", id: :integer, charset: "utf8", force: :cascade do |t|
55 + create_table "contests", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
28 t.string "title"
56 t.string "title"
29 t.boolean "enabled"
57 t.boolean "enabled"
30 t.datetime "created_at", precision: nil, null: false
58 t.datetime "created_at", precision: nil, null: false
@@ -32,39 +60,39
32 t.string "name"
60 t.string "name"
33 end
61 end
34
62
35 - create_table "contests_problems", id: false, charset: "utf8", force: :cascade do |t|
63 + create_table "contests_problems", id: false, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
36 t.integer "contest_id"
64 t.integer "contest_id"
37 t.integer "problem_id"
65 t.integer "problem_id"
38 end
66 end
39
67
40 - create_table "contests_users", id: false, charset: "utf8", force: :cascade do |t|
68 + create_table "contests_users", id: false, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
41 t.integer "contest_id"
69 t.integer "contest_id"
42 t.integer "user_id"
70 t.integer "user_id"
43 end
71 end
44
72
45 - create_table "countries", id: :integer, charset: "utf8", force: :cascade do |t|
73 + create_table "countries", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
46 t.string "name"
74 t.string "name"
47 t.datetime "created_at", precision: nil, null: false
75 t.datetime "created_at", precision: nil, null: false
48 t.datetime "updated_at", precision: nil, null: false
76 t.datetime "updated_at", precision: nil, null: false
49 end
77 end
50
78
51 - create_table "descriptions", id: :integer, charset: "utf8", force: :cascade do |t|
79 + create_table "descriptions", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
52 - t.text "body", size: :medium
80 + t.text "body"
53 t.boolean "markdowned"
81 t.boolean "markdowned"
54 t.datetime "created_at", precision: nil, null: false
82 t.datetime "created_at", precision: nil, null: false
55 t.datetime "updated_at", precision: nil, null: false
83 t.datetime "updated_at", precision: nil, null: false
56 end
84 end
57
85
58 - create_table "grader_configurations", id: :integer, charset: "utf8", force: :cascade do |t|
86 + create_table "grader_configurations", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
59 t.string "key"
87 t.string "key"
60 t.string "value_type"
88 t.string "value_type"
61 t.string "value"
89 t.string "value"
62 t.datetime "created_at", precision: nil, null: false
90 t.datetime "created_at", precision: nil, null: false
63 t.datetime "updated_at", precision: nil, null: false
91 t.datetime "updated_at", precision: nil, null: false
64 - t.text "description", size: :medium
92 + t.text "description"
65 end
93 end
66
94
67 - create_table "grader_processes", id: :integer, charset: "utf8", force: :cascade do |t|
95 + create_table "grader_processes", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
68 t.string "host"
96 t.string "host"
69 t.integer "pid"
97 t.integer "pid"
70 t.string "mode"
98 t.string "mode"
@@ -95,7 +123,7
95 t.index ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id"
123 t.index ["user_id", "group_id"], name: "index_groups_users_on_user_id_and_group_id"
96 end
124 end
97
125
98 - create_table "heart_beats", id: :integer, charset: "latin1", force: :cascade do |t|
126 + create_table "heart_beats", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
99 t.integer "user_id"
127 t.integer "user_id"
100 t.string "ip_address"
128 t.string "ip_address"
101 t.datetime "created_at", precision: nil, null: false
129 t.datetime "created_at", precision: nil, null: false
@@ -104,14 +132,14
104 t.index ["updated_at"], name: "index_heart_beats_on_updated_at"
132 t.index ["updated_at"], name: "index_heart_beats_on_updated_at"
105 end
133 end
106
134
107 - create_table "languages", id: :integer, charset: "utf8", force: :cascade do |t|
135 + create_table "languages", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
108 t.string "name", limit: 10
136 t.string "name", limit: 10
109 t.string "pretty_name"
137 t.string "pretty_name"
110 t.string "ext", limit: 10
138 t.string "ext", limit: 10
111 t.string "common_ext"
139 t.string "common_ext"
112 end
140 end
113
141
114 - create_table "logins", id: :integer, charset: "latin1", force: :cascade do |t|
142 + create_table "logins", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
115 t.integer "user_id"
143 t.integer "user_id"
116 t.string "ip_address"
144 t.string "ip_address"
117 t.datetime "created_at", precision: nil, null: false
145 t.datetime "created_at", precision: nil, null: false
@@ -119,18 +147,18
119 t.index ["user_id"], name: "index_logins_on_user_id"
147 t.index ["user_id"], name: "index_logins_on_user_id"
120 end
148 end
121
149
122 - create_table "messages", id: :integer, charset: "utf8", force: :cascade do |t|
150 + create_table "messages", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
123 t.integer "sender_id"
151 t.integer "sender_id"
124 t.integer "receiver_id"
152 t.integer "receiver_id"
125 t.integer "replying_message_id"
153 t.integer "replying_message_id"
126 - t.text "body", size: :medium
154 + t.text "body"
127 t.boolean "replied"
155 t.boolean "replied"
128 t.datetime "created_at", precision: nil, null: false
156 t.datetime "created_at", precision: nil, null: false
129 t.datetime "updated_at", precision: nil, null: false
157 t.datetime "updated_at", precision: nil, null: false
130 end
158 end
131
159
132 - create_table "problems", id: :bigint, default: nil, charset: "utf8", force: :cascade do |t|
160 + create_table "problems", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
133 - t.string "name", limit: 100
161 + t.string "name", limit: 30
134 t.string "full_name"
162 t.string "full_name"
135 t.integer "full_score"
163 t.integer "full_score"
136 t.date "date_added"
164 t.date "date_added"
@@ -142,47 +170,49
142 t.string "description_filename"
170 t.string "description_filename"
143 t.boolean "view_testcase"
171 t.boolean "view_testcase"
144 t.integer "difficulty"
172 t.integer "difficulty"
173 + t.text "description"
174 + t.boolean "markdown"
145 end
175 end
146
176
147 - create_table "problems_tags", id: :bigint, default: nil, charset: "latin1", force: :cascade do |t|
177 + create_table "problems_tags", id: :integer, charset: "latin1", force: :cascade do |t|
148 - t.bigint "problem_id"
178 + t.integer "problem_id"
149 t.integer "tag_id"
179 t.integer "tag_id"
150 t.index ["problem_id", "tag_id"], name: "index_problems_tags_on_problem_id_and_tag_id", unique: true
180 t.index ["problem_id", "tag_id"], name: "index_problems_tags_on_problem_id_and_tag_id", unique: true
151 t.index ["problem_id"], name: "index_problems_tags_on_problem_id"
181 t.index ["problem_id"], name: "index_problems_tags_on_problem_id"
152 t.index ["tag_id"], name: "index_problems_tags_on_tag_id"
182 t.index ["tag_id"], name: "index_problems_tags_on_tag_id"
153 end
183 end
154
184
155 - create_table "rights", id: :integer, charset: "utf8", force: :cascade do |t|
185 + create_table "rights", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
156 t.string "name"
186 t.string "name"
157 t.string "controller"
187 t.string "controller"
158 t.string "action"
188 t.string "action"
159 end
189 end
160
190
161 - create_table "rights_roles", id: false, charset: "utf8", force: :cascade do |t|
191 + create_table "rights_roles", id: false, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
162 t.integer "right_id"
192 t.integer "right_id"
163 t.integer "role_id"
193 t.integer "role_id"
164 t.index ["role_id"], name: "index_rights_roles_on_role_id"
194 t.index ["role_id"], name: "index_rights_roles_on_role_id"
165 end
195 end
166
196
167 - create_table "roles", id: :integer, charset: "utf8", force: :cascade do |t|
197 + create_table "roles", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
168 t.string "name"
198 t.string "name"
169 end
199 end
170
200
171 - create_table "roles_users", id: false, charset: "utf8", force: :cascade do |t|
201 + create_table "roles_users", id: false, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
172 t.integer "role_id"
202 t.integer "role_id"
173 t.integer "user_id"
203 t.integer "user_id"
174 t.index ["user_id"], name: "index_roles_users_on_user_id"
204 t.index ["user_id"], name: "index_roles_users_on_user_id"
175 end
205 end
176
206
177 - create_table "sessions", id: :integer, charset: "utf8", force: :cascade do |t|
207 + create_table "sessions", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
178 t.string "session_id"
208 t.string "session_id"
179 - t.text "data", size: :medium
209 + t.text "data"
180 t.datetime "updated_at", precision: nil
210 t.datetime "updated_at", precision: nil
181 t.index ["session_id"], name: "index_sessions_on_session_id"
211 t.index ["session_id"], name: "index_sessions_on_session_id"
182 t.index ["updated_at"], name: "index_sessions_on_updated_at"
212 t.index ["updated_at"], name: "index_sessions_on_updated_at"
183 end
213 end
184
214
185 - create_table "sites", id: :integer, charset: "utf8", force: :cascade do |t|
215 + create_table "sites", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
186 t.string "name"
216 t.string "name"
187 t.boolean "started"
217 t.boolean "started"
188 t.datetime "start_time", precision: nil
218 t.datetime "start_time", precision: nil
@@ -192,23 +222,14
192 t.string "password"
222 t.string "password"
193 end
223 end
194
224
195 - create_table "solutions", charset: "latin1", force: :cascade do |t|
225 + create_table "submission_view_logs", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
196 - t.string "solution"
197 - t.bigint "problem_id"
198 - t.bigint "submission_id"
199 - t.integer "type"
200 - t.index ["problem_id"], name: "index_solutions_on_problem_id"
201 - t.index ["submission_id"], name: "index_solutions_on_submission_id"
202 - end
203 -
204 - create_table "submission_view_logs", id: :integer, charset: "latin1", force: :cascade do |t|
205 t.integer "user_id"
226 t.integer "user_id"
206 t.integer "submission_id"
227 t.integer "submission_id"
207 t.datetime "created_at", precision: nil, null: false
228 t.datetime "created_at", precision: nil, null: false
208 t.datetime "updated_at", precision: nil, null: false
229 t.datetime "updated_at", precision: nil, null: false
209 end
230 end
210
231
211 - create_table "submissions", id: :bigint, default: nil, charset: "utf8", force: :cascade do |t|
232 + create_table "submissions", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
212 t.integer "user_id"
233 t.integer "user_id"
213 t.integer "problem_id"
234 t.integer "problem_id"
214 t.integer "language_id"
235 t.integer "language_id"
@@ -216,10 +237,10
216 t.binary "binary"
237 t.binary "binary"
217 t.datetime "submitted_at", precision: nil
238 t.datetime "submitted_at", precision: nil
218 t.datetime "compiled_at", precision: nil
239 t.datetime "compiled_at", precision: nil
219 - t.text "compiler_message", size: :medium
240 + t.text "compiler_message"
220 t.datetime "graded_at", precision: nil
241 t.datetime "graded_at", precision: nil
221 t.integer "points"
242 t.integer "points"
222 - t.text "grader_comment", size: :medium
243 + t.text "grader_comment"
223 t.integer "number"
244 t.integer "number"
224 t.string "source_filename"
245 t.string "source_filename"
225 t.float "max_runtime"
246 t.float "max_runtime"
@@ -240,7 +261,7
240 t.datetime "updated_at", precision: nil, null: false
261 t.datetime "updated_at", precision: nil, null: false
241 end
262 end
242
263
243 - create_table "tasks", id: :integer, charset: "utf8", force: :cascade do |t|
264 + create_table "tasks", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
244 t.integer "submission_id"
265 t.integer "submission_id"
245 t.datetime "created_at", precision: nil
266 t.datetime "created_at", precision: nil
246 t.integer "status"
267 t.integer "status"
@@ -249,15 +270,15
249 t.index ["submission_id"], name: "index_tasks_on_submission_id"
270 t.index ["submission_id"], name: "index_tasks_on_submission_id"
250 end
271 end
251
272
252 - create_table "test_pairs", id: :integer, charset: "utf8", force: :cascade do |t|
273 + create_table "test_pairs", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
253 t.integer "problem_id"
274 t.integer "problem_id"
254 - t.text "input", size: :long
275 + t.text "input", size: :medium
255 - t.text "solution", size: :long
276 + t.text "solution", size: :medium
256 t.datetime "created_at", precision: nil, null: false
277 t.datetime "created_at", precision: nil, null: false
257 t.datetime "updated_at", precision: nil, null: false
278 t.datetime "updated_at", precision: nil, null: false
258 end
279 end
259
280
260 - create_table "test_requests", id: :integer, charset: "utf8", force: :cascade do |t|
281 + create_table "test_requests", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
261 t.integer "user_id"
282 t.integer "user_id"
262 t.integer "problem_id"
283 t.integer "problem_id"
263 t.integer "submission_id"
284 t.integer "submission_id"
@@ -268,7 +289,7
268 t.datetime "updated_at", precision: nil, null: false
289 t.datetime "updated_at", precision: nil, null: false
269 t.datetime "submitted_at", precision: nil
290 t.datetime "submitted_at", precision: nil
270 t.datetime "compiled_at", precision: nil
291 t.datetime "compiled_at", precision: nil
271 - t.text "compiler_message", size: :medium
292 + t.text "compiler_message"
272 t.datetime "graded_at", precision: nil
293 t.datetime "graded_at", precision: nil
273 t.string "grader_comment"
294 t.string "grader_comment"
274 t.datetime "created_at", precision: nil, null: false
295 t.datetime "created_at", precision: nil, null: false
@@ -285,12 +306,12
285 t.integer "score"
306 t.integer "score"
286 t.text "input", size: :long
307 t.text "input", size: :long
287 t.text "sol", size: :long
308 t.text "sol", size: :long
288 - t.datetime "created_at", precision: nil, null: false
309 + t.datetime "created_at", precision: nil
289 - t.datetime "updated_at", precision: nil, null: false
310 + t.datetime "updated_at", precision: nil
290 t.index ["problem_id"], name: "index_testcases_on_problem_id"
311 t.index ["problem_id"], name: "index_testcases_on_problem_id"
291 end
312 end
292
313
293 - create_table "user_contest_stats", id: :integer, charset: "utf8", force: :cascade do |t|
314 + create_table "user_contest_stats", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
294 t.integer "user_id"
315 t.integer "user_id"
295 t.datetime "started_at", precision: nil
316 t.datetime "started_at", precision: nil
296 t.datetime "created_at", precision: nil, null: false
317 t.datetime "created_at", precision: nil, null: false
@@ -298,7 +319,7
298 t.boolean "forced_logout"
319 t.boolean "forced_logout"
299 end
320 end
300
321
301 - create_table "users", id: :integer, charset: "utf8", force: :cascade do |t|
322 + create_table "users", id: :integer, charset: "utf8mb3", collation: "utf8mb3_unicode_ci", force: :cascade do |t|
302 t.string "login", limit: 50
323 t.string "login", limit: 50
303 t.string "full_name"
324 t.string "full_name"
304 t.string "hashed_password"
325 t.string "hashed_password"
@@ -310,16 +331,16
310 t.boolean "activated", default: false
331 t.boolean "activated", default: false
311 t.datetime "created_at", precision: nil
332 t.datetime "created_at", precision: nil
312 t.datetime "updated_at", precision: nil
333 t.datetime "updated_at", precision: nil
313 - t.string "section"
314 t.boolean "enabled", default: true
334 t.boolean "enabled", default: true
315 t.string "remark"
335 t.string "remark"
316 t.string "last_ip"
336 t.string "last_ip"
337 + t.string "section"
317 t.integer "default_language"
338 t.integer "default_language"
318 t.index ["login"], name: "index_users_on_login", unique: true
339 t.index ["login"], name: "index_users_on_login", unique: true
319 end
340 end
320
341
342 + add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
343 + add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
321 add_foreign_key "problems_tags", "problems"
344 add_foreign_key "problems_tags", "problems"
322 add_foreign_key "problems_tags", "tags"
345 add_foreign_key "problems_tags", "tags"
323 - add_foreign_key "solutions", "problems"
324 - add_foreign_key "solutions", "submissions"
325 end
346 end
deleted file
You need to be logged in to leave comments. Login now