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

r874:8ff5fd21c79c - - 12 files changed: 120 inserted, 95 deleted

@@ -0,0 +1,23
1 + .card.border-info.mb-2
2 + .card-header.text-bg-info.border-info
3 + Select a Task
4 + .card-body
5 + .row
6 + .col-6
7 + = select 'submission',
8 + 'problem_id',
9 + problems.collect {|p| ["[#{p.name}] #{p.full_name}", send(target_url_method,p.id)]},
10 + { selected: (selected_problem ? problem_submissions_url(selected_problem) : -1) },
11 + { class: 'select2 form-control'}
12 + .col-6
13 + %a.btn.btn-primary.go-button#problem_go{data: {source: '#submission_problem_id'}} Go
14 + :javascript
15 + $(".go-button").on('click', function(event) {
16 + var link, url;
17 + link = $(this).attr("data-source");
18 + url = $(link).val();
19 + if (url) {
20 + window.location.href = url;
21 + }
22 + });
23 +
@@ -1,24 +1,23
1 1 source 'https://rubygems.org'
2 2 git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3 3
4 4 ruby '3.1.2'
5 5
6 6 #rails
7 7 gem 'rails', '~>7.0'
8 8
9 9 # The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]
10 10 gem "sprockets-rails"
11 11
12 - gem 'activerecord-session_store'
13 12 gem 'puma'
14 13
15 14 # Reduces boot times through caching; required in config/boot.rb
16 15 gem 'bootsnap', require: false
17 16
18 17 # Bundle edge Rails instead:
19 18 # gem 'rails', :git => 'git://github.com/rails/rails.git'
20 19
21 20 #---------------- database ---------------------
22 21 #the database
23 22 gem 'mysql2'
24 23 #for testing
@@ -57,30 +57,24
57 57 builder (~> 3.1)
58 58 erubi (~> 1.4)
59 59 rails-dom-testing (~> 2.0)
60 60 rails-html-sanitizer (~> 1.1, >= 1.2.0)
61 61 activejob (7.0.4)
62 62 activesupport (= 7.0.4)
63 63 globalid (>= 0.3.6)
64 64 activemodel (7.0.4)
65 65 activesupport (= 7.0.4)
66 66 activerecord (7.0.4)
67 67 activemodel (= 7.0.4)
68 68 activesupport (= 7.0.4)
69 - activerecord-session_store (2.0.0)
70 - actionpack (>= 5.2.4.1)
71 - activerecord (>= 5.2.4.1)
72 - multi_json (~> 1.11, >= 1.11.2)
73 - rack (>= 2.0.8, < 3)
74 - railties (>= 5.2.4.1)
75 69 activestorage (7.0.4)
76 70 actionpack (= 7.0.4)
77 71 activejob (= 7.0.4)
78 72 activerecord (= 7.0.4)
79 73 activesupport (= 7.0.4)
80 74 marcel (~> 1.0)
81 75 mini_mime (>= 1.1.0)
82 76 activesupport (7.0.4)
83 77 concurrent-ruby (~> 1.0, >= 1.0.2)
84 78 i18n (>= 1.6, < 2)
85 79 minitest (>= 5.1)
86 80 tzinfo (~> 2.0)
@@ -136,25 +130,24
136 130 html2haml (>= 1.0.1)
137 131 railties (>= 5.1)
138 132 html2haml (2.2.0)
139 133 erubis (~> 2.7.0)
140 134 haml (>= 4.0, < 6)
141 135 nokogiri (>= 1.6.0)
142 136 ruby_parser (~> 3.5)
143 137 i18n (1.12.0)
144 138 concurrent-ruby (~> 1.0)
145 139 importmap-rails (1.1.5)
146 140 actionpack (>= 6.0.0)
147 141 railties (>= 6.0.0)
148 - in_place_editing (1.2.0)
149 142 jbuilder (2.11.5)
150 143 actionview (>= 5.0.0)
151 144 activesupport (>= 5.0.0)
152 145 jquery-rails (4.5.0)
153 146 rails-dom-testing (>= 1, < 3)
154 147 railties (>= 4.2.0)
155 148 thor (>= 0.14, < 2.0)
156 149 listen (3.0.8)
157 150 rb-fsevent (~> 0.9, >= 0.9.4)
158 151 rb-inotify (~> 0.9, >= 0.9.7)
159 152 loofah (2.19.0)
160 153 crass (~> 1.0.2)
@@ -167,25 +160,24
167 160 matrix (0.4.2)
168 161 method_source (1.0.0)
169 162 mini_mime (1.1.2)
170 163 minitest (5.16.3)
171 164 minitest-reporters (1.5.0)
172 165 ansi
173 166 builder
174 167 minitest (>= 5.0)
175 168 ruby-progressbar
176 169 momentjs-rails (2.29.4.1)
177 170 railties (>= 3.1)
178 171 msgpack (1.5.6)
179 - multi_json (1.15.0)
180 172 mysql2 (0.5.4)
181 173 net-imap (0.2.3)
182 174 digest
183 175 net-protocol
184 176 strscan
185 177 net-pop (0.1.1)
186 178 digest
187 179 net-protocol
188 180 timeout
189 181 net-protocol (0.1.3)
190 182 timeout
191 183 net-smtp (0.3.1)
@@ -290,36 +282,34
290 282 websocket-driver (0.7.5)
291 283 websocket-extensions (>= 0.1.0)
292 284 websocket-extensions (0.1.5)
293 285 xpath (3.2.0)
294 286 nokogiri (~> 1.8)
295 287 zeitwerk (2.6.0)
296 288
297 289 PLATFORMS
298 290 x86_64-linux
299 291
300 292 DEPENDENCIES
301 293 ace-rails-ap
302 - activerecord-session_store
303 294 best_in_place!
304 295 bootsnap
305 296 bootstrap (~> 5.2)
306 297 byebug
307 298 capybara
308 299 coffee-rails
309 300 fuzzy-string-match
310 301 haml
311 302 haml-rails
312 303 importmap-rails (~> 1.1)
313 - in_place_editing
314 304 jbuilder
315 305 jquery-rails
316 306 listen (>= 3.0.5, < 3.2)
317 307 mail
318 308 material_icons
319 309 minitest-reporters
320 310 momentjs-rails
321 311 mysql2
322 312 puma
323 313 rails (~> 7.0)
324 314 rdiscount
325 315 rouge
@@ -17,32 +17,24
17 17 $('.btn-file :file').on('fileselect', function(event, numFiles, label) {
18 18 var input, log;
19 19 input = $(this).parents('.input-group').find(':text');
20 20 log = numFiles > 1 ? numFiles + ' files selected' : label;
21 21 if (input.length) {
22 22 input.val(log);
23 23 } else {
24 24 if (log) {
25 25 alert(log);
26 26 }
27 27 }
28 28 });
29 - $(".go-button").on('click', function(event) {
30 - var link, url;
31 - link = $(this).attr("data-source");
32 - url = $(link).val();
33 - if (url) {
34 - window.location.href = url;
35 - }
36 - });
37 29 $('.ajax-toggle').on('click', function(event) {
38 30 var target;
39 31 target = $(event.target);
40 32 target.removeClass('btn-default');
41 33 target.removeClass('btn-success');
42 34 target.addClass('btn-warning');
43 35 target.text('...');
44 36 });
45 37 if ($("#editor").length > 0) {
46 38 e = ace.edit("editor");
47 39 e.setTheme('ace/theme/merbivore');
48 40 e.getSession().setTabSize(2);
@@ -20,14 +20,15
20 20 <link href="https://fonts.googleapis.com/css2?family=Bai+Jamjuree:ital,wght@0,200;0,400;0,600;1,200;1,400;1,600&family=Krub:ital,wght@0,200;0,400;0,600;1,200;1,400;1,600&family=Sarabun:ital,wght@0,200;0,400;0,600;1,200;1,400;1,600&display=swap" rel="stylesheet">
21 21 <link href="https://fonts.googleapis.com/css2?family=Mitr:ital,wght@0,300;1,300&family=Kodchasan:ital,wght@0,200;0,400;0,600;1,200;1,400;1,600&family=Noto+Serif+Thai:ital,wght@0,200;0,400;0,600;1,200;1,400;1,600&family=Noto+Sans+Thai:ital,wght@0,200;0,400;0,600;1,200;1,400;1,600&display=swap" rel="stylesheet">
22 22 <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+Thai:ital,wght@0,200;0,400;0,600;1,200;1,400;1,600&family=Noto+Sans+Thai:ital,wght@0,200;0,400;0,600;1,200;1,400;1,600&display=swap" rel="stylesheet">
23 23 <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+Thai:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&display=swap" rel="stylesheet">
24 24 <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Thai:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&display=swap" rel="stylesheet">
25 25 <link href="https://fonts.googleapis.com/css2?family=Sarabun:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&display=swap" rel="stylesheet">
26 26
27 27 %body
28 28 - unless local_assigns[:skip_header]
29 29 = render 'layouts/header'
30 30
31 31 /= content_tag(:p,flash[:notice],class: 'alert alert-success') if flash[:notice]!=nil
32 + .container-fluid
32 33 = flash_messages
33 34 = yield
@@ -1,13 +1,56
1 - %b= GraderConfiguration['ui.front.welcome_message']
1 +
2 + .card
3 + .card-body
4 + .card-title
5 + %h3= GraderConfiguration['ui.front.welcome_message']
6 + - if !@hidelogin
7 + .card-subtitle=t 'login.message'
8 +
9 + - if flash[:notice]
10 + %hr/
11 + %b= flash[:notice]
12 + %hr/
13 +
14 + .card
15 + .card-body{ style: "background: #eeeeff;"}
16 + = form_with url: login_login_path do |f|
17 + .mb-3
18 + = f.label :login, "Login", class: 'form-label'
19 + = f.text_field :login, class: 'form-control'
20 + .mb-3
21 + = f.label :password, "Password", class: 'form-label'
22 + = f.password_field :password, class: 'form-control'
23 + - unless GraderConfiguration['right.bypass_agreement']
24 + .col-sm-offset-3.col-sm-9
25 + .checkbox
26 + %label
27 + = check_box_tag 'accept_agree'
28 + ยอมรับข้อตกลงการใช้งาน
29 + .mb-3
30 + .col-sm-offset-3.col-sm-9
31 + = submit_tag t('login.login_submit'), class: 'btn btn-primary'
32 + - else
33 + Login is not possible right now
34 +
35 + %br/
36 +
37 + - if GraderConfiguration['system.online_registration']
38 + =t 'login.participation'
39 + %b
40 + = "#{t 'login.please'} "
41 + = link_to "#{t 'login.register'}", :controller => :users, :action => :new
42 + %br/
43 + = link_to "#{t 'login.forget_password'}", :controller => :users, :action => :forget
44 + -#
2 45 %br/
3 46
4 47 - if !@hidelogin
5 48 =t 'login.message'
6 49 %br/
7 50 %br/
8 51
9 52 - if flash[:notice]
10 53 %hr/
11 54 %b= flash[:notice]
12 55 %hr/
13 56
@@ -23,21 +66,23
23 66 =password_field_tag :password, nil, class: 'form-control'
24 67 - unless GraderConfiguration['right.bypass_agreement']
25 68 .form-group
26 69 .col-sm-offset-3.col-sm-9
27 70 .checkbox
28 71 %label
29 72 = check_box_tag 'accept_agree'
30 73 ยอมรับข้อตกลงการใช้งาน
31 74
32 75 .form-group
33 76 .col-sm-offset-3.col-sm-9
34 77 = submit_tag t('login.login_submit'), class: 'btn btn-primary'
78 + - else
79 +
35 80 %br/
36 81
37 82 - if GraderConfiguration['system.online_registration']
38 83 =t 'login.participation'
39 84 %b
40 85 = "#{t 'login.please'} "
41 86 = link_to "#{t 'login.register'}", :controller => :users, :action => :new
42 87 %br/
43 88 = link_to "#{t 'login.forget_password'}", :controller => :users, :action => :forget
@@ -15,47 +15,46
15 15 position: absolute;
16 16 left: 25px;
17 17 bottom: 5px;
18 18 border: 1px solid;
19 19 padding: 5px;
20 20 background-color: #FFF;
21 21 word-wrap: break-word;
22 22 z-index: 9999;
23 23 overflow: auto;
24 24 }
25 25
26 26
27 - .container-fluid
28 - .row
27 + .row.mb-3
29 28 .col-md-8
30 29 .card
31 30 .card-body
32 31 %h2.card-title Submission History
33 32 %canvas#chart{height: '50px'}
34 33
35 34 .col-md-4
36 35 .card
37 36 .card-body
38 37 %h2.card-title General Info
39 38 .row
40 39 .col-sm-6
41 40 Subs
42 41 .col-sm-6
43 42 = @summary[:count]
44 43 .row
45 44 .col-sm-6
46 45 Solved/Attempted User
47 46 .col-sm-6
48 47 #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
49 - .row
48 + .row.mb-3
50 49 .col-md-4
51 50 .card
52 51 .card-body
53 52 %h2.card-title Model submission
54 53 %table.table.table-hover
55 54 %thead
56 55 %tr
57 56 %th #Sub (lang)
58 57 %th Author
59 58 %tbody
60 59 - @model_subs.each do |sub|
61 60 %tr
@@ -1,30 +1,20
1 1
2 2 /- if params[:id]
3 3 / %h1 Tasks Hall of Fame
4 4 / = link_to('[back to All-Time Hall of Fame]', action: 'problem_hof', id: nil )
5 5 /- else
6 6 / %h1 All-Time Hall of Fame
7 7
8 - .panel.panel-info
9 - .panel-heading
10 - Select Task
11 - .panel-body
12 - .form-inline
13 - = select 'report',
14 - 'problem_id',
15 - @problems.collect {|p| ["[#{p.name}] #{p.full_name}", problem_hof_report_path(p)]},
16 - {:selected => problem_hof_report_path(@problem)},
17 - { class: 'select2 form-control' }
18 - %button.btn.btn-primary.btn-sm.go-button#problem_go{data: {source: "#report_problem_id"}} Go
19 -
8 + .row.mb-5
9 + .col-md-6
10 + = render 'problem_chooser', {problems: @problems, selected_problem: @problem, target_url_method: :problem_hof_report_path}
20 11
21 12 - unless params[:id]
22 - /=render partial: 'all_time_hof'
23 13 Please select a problem.
24 14 - else
25 - %h1
15 + %h1.mt-3
26 16 [#{Problem.find(params[:id]).name}] #{Problem.find(params[:id]).full_name}
27 17 - if @current_user.has_role?('ta')
28 18 %a{href:stat_problem_path(@problem)} (stat)
29 19 =render partial: 'task_hof'
30 20
@@ -1,25 +1,13
1 - .card.border-info.mb-2
2 - .card-header.text-bg-info.border-info
3 - Select Problems
4 - .card-body
5 - .row
6 - .col-6
7 - = select 'submission',
8 - 'problem_id',
9 - @problems.collect {|p| ["[#{p.name}] #{p.full_name}", problem_submissions_url(p.id)]},
10 - { selected: (@problem ? problem_submissions_url(@problem) : -1) },
11 - { class: 'select2 form-control'}
12 - .col-6
13 - %a.btn.btn-primary.go-button#problem_go{data: {source: '#submission_problem_id'}} Go
1 + = render 'problem_chooser', {problems: @problems, selected_problem: @problem, target_url_method: :problem_submissions_path}
14 2
15 3 - if @problem!=nil
16 4 %h2= "Task: #{@problem.full_name} (#{@problem.name})"
17 5
18 6 - if @submissions!=nil
19 7 - if @submissions.length>0
20 8 %table.table
21 9 %thead
22 10 %th No.
23 11 %th.text-right #
24 12 %th At
25 13 %th Source
@@ -1,35 +1,35
1 1 %h1 Users
2 2
3 - .panel.panel-primary
4 - .panel-title.panel-heading
3 + .card.border-primary
4 + .card-header.text-bg-primary.border-primary
5 5 Quick Add
6 - .panel-body
7 - = form_tag( {method: 'post'}, {class: 'form-inline'}) do
8 - .form-group
9 - = label_tag 'user_login', 'Login'
10 - = text_field 'user', 'login', :size => 10,class: 'form-control'
6 + .card-body
7 + = form_with url: 'asd', class: 'row row-cols-lg-auto g-3 align-items-center' do |f|
8 + .col-12
9 + = f.label 'user_login', 'Login'
10 + = f.text_field 'login', :size => 10,class: 'form-control'
11 11 .form-group
12 - = label_tag 'user_full_name', 'Full Name'
13 - = text_field 'user', 'full_name', :size => 10,class: 'form-control'
12 + = f.label 'user_full_name', 'Full Name'
13 + = f.text_field 'full_name', :size => 10,class: 'form-control'
14 14 .form-group
15 - = label_tag 'user_password', 'Password'
16 - = text_field 'user', 'password', :size => 10,class: 'form-control'
15 + = f.label 'user_password', 'Password'
16 + = f.text_field 'password', :size => 10,class: 'form-control'
17 17 .form-group
18 - = label_tag 'user_password_confirmation', 'Confirm'
19 - = text_field 'user', 'password_confirmation', :size => 10,class: 'form-control'
18 + = f.label 'user_password_confirmation', 'Confirm'
19 + = f.text_field 'password_confirmation', :size => 10,class: 'form-control'
20 20 .form-group
21 - = label_tag 'user_email', 'email'
22 - = text_field 'user', 'email', :size => 10,class: 'form-control'
23 - =submit_tag "Create", class: 'btn btn-primary'
21 + = f.label 'user_email', 'email'
22 + = f.text_field 'email', :size => 10,class: 'form-control'
23 + =submit_tag "Create", class: 'btn btn-primary align-items-bottom'
24 24
25 25 .panel.panel-primary
26 26 .panel-title.panel-heading
27 27 Import from site management
28 28 .panel-body
29 29 = form_tag({:action => 'import'}, :multipart => true,class: 'form form-inline') do
30 30 .form-group
31 31 = label_tag :file, 'File:'
32 32 .input-group
33 33 %span.input-group-btn
34 34 %span.btn.btn-default.btn-file
35 35 Browse
@@ -1,17 +1,17
1 1 # frozen_string_literal: true
2 2 #
3 3 # Uncomment this and change the path if necessary to include your own
4 4 # components.
5 - # See https://github.com/plataformatec/simple_form#custom-components to know
5 + # See https://github.com/heartcombo/simple_form#custom-components to know
6 6 # more about custom components.
7 7 # Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
8 8 #
9 9 # Use this setup block to configure all options available in SimpleForm.
10 10 SimpleForm.setup do |config|
11 11 # Wrappers are used by the form builder to generate a
12 12 # complete input. You can remove any component from the
13 13 # wrapper, change the order or even add your own to the
14 14 # stack. The options given below are used to wrap the
15 15 # whole input.
16 16 config.wrappers :default, class: :input,
17 17 hint_class: :field_with_hint, error_class: :field_with_errors, valid_class: :field_without_errors do |b|
@@ -120,27 +120,24
120 120 # config.generate_additional_classes_for = [:wrapper, :label, :input]
121 121
122 122 # Whether attributes are required by default (or not). Default is true.
123 123 # config.required_by_default = true
124 124
125 125 # Tell browsers whether to use the native HTML5 validations (novalidate form option).
126 126 # These validations are enabled in SimpleForm's internal config but disabled by default
127 127 # in this configuration, which is recommended due to some quirks from different browsers.
128 128 # To stop SimpleForm from generating the novalidate option, enabling the HTML5 validations,
129 129 # change this configuration to true.
130 130 config.browser_validations = false
131 131
132 - # Collection of methods to detect if a file type was given.
133 - # config.file_methods = [ :mounted_as, :file?, :public_filename, :attached? ]
134 -
135 132 # Custom mappings for input types. This should be a hash containing a regexp
136 133 # to match as key, and the input type that will be used when the field name
137 134 # matches the regexp as value.
138 135 # config.input_mappings = { /count/ => :integer }
139 136
140 137 # Custom wrappers for input types. This should be a hash containing an input
141 138 # type as key and the wrapper that will be used for all inputs with specified type.
142 139 # config.wrapper_mappings = { string: :prepend }
143 140
144 141 # Namespaces where SimpleForm should look for custom input classes that
145 142 # override default inputs.
146 143 # config.custom_inputs_namespaces << "CustomInputs"
@@ -1,23 +1,23
1 1 # frozen_string_literal: true
2 2
3 3 # Please do not make direct changes to this file!
4 4 # This generator is maintained by the community around simple_form-bootstrap:
5 5 # https://github.com/rafaelfranca/simple_form-bootstrap
6 6 # All future development, tests, and organization should happen there.
7 - # Background history: https://github.com/plataformatec/simple_form/issues/1561
7 + # Background history: https://github.com/heartcombo/simple_form/issues/1561
8 8
9 9 # Uncomment this and change the path if necessary to include your own
10 10 # components.
11 - # See https://github.com/plataformatec/simple_form#custom-components
11 + # See https://github.com/heartcombo/simple_form#custom-components
12 12 # to know more about custom components.
13 13 # Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
14 14
15 15 # Use this setup block to configure all options available in SimpleForm.
16 16 SimpleForm.setup do |config|
17 17 # Default class for buttons
18 18 config.button_class = 'btn'
19 19
20 20 # Define the default class of the input wrapper of the boolean input.
21 21 config.boolean_label_class = 'form-check-label'
22 22
23 23 # How the label text should be generated altogether with the required text.
@@ -48,84 +48,84
48 48
49 49 # vertical forms
50 50 #
51 51 # vertical default_wrapper
52 52 config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
53 53 b.use :html5
54 54 b.use :placeholder
55 55 b.optional :maxlength
56 56 b.optional :minlength
57 57 b.optional :pattern
58 58 b.optional :min_max
59 59 b.optional :readonly
60 - b.use :label, class: 'form-control-label'
60 + b.use :label
61 61 b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
62 62 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
63 63 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
64 64 end
65 65
66 66 # vertical input for boolean
67 67 config.wrappers :vertical_boolean, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
68 68 b.use :html5
69 69 b.optional :readonly
70 70 b.wrapper :form_check_wrapper, tag: 'div', class: 'form-check' do |bb|
71 71 bb.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
72 72 bb.use :label, class: 'form-check-label'
73 73 bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
74 74 bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
75 75 end
76 76 end
77 77
78 78 # vertical input for radio buttons and check boxes
79 - config.wrappers :vertical_collection, item_wrapper_class: 'form-check', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
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|
80 80 b.use :html5
81 81 b.optional :readonly
82 82 b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
83 83 ba.use :label_text
84 84 end
85 85 b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
86 86 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
87 87 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
88 88 end
89 89
90 90 # vertical input for inline radio buttons and check boxes
91 - config.wrappers :vertical_collection_inline, item_wrapper_class: 'form-check form-check-inline', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
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|
92 92 b.use :html5
93 93 b.optional :readonly
94 94 b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
95 95 ba.use :label_text
96 96 end
97 97 b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
98 98 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
99 99 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
100 100 end
101 101
102 102 # vertical file input
103 103 config.wrappers :vertical_file, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
104 104 b.use :html5
105 105 b.use :placeholder
106 106 b.optional :maxlength
107 107 b.optional :minlength
108 108 b.optional :readonly
109 109 b.use :label
110 110 b.use :input, class: 'form-control-file', error_class: 'is-invalid', valid_class: 'is-valid'
111 - b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
111 + b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
112 112 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
113 113 end
114 114
115 115 # vertical multi select
116 116 config.wrappers :vertical_multi_select, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
117 117 b.use :html5
118 118 b.optional :readonly
119 - b.use :label, class: 'form-control-label'
119 + b.use :label
120 120 b.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |ba|
121 121 ba.use :input, class: 'form-control mx-1', error_class: 'is-invalid', valid_class: 'is-valid'
122 122 end
123 123 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
124 124 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
125 125 end
126 126
127 127 # vertical range input
128 128 config.wrappers :vertical_range, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
129 129 b.use :html5
130 130 b.use :placeholder
131 131 b.optional :readonly
@@ -165,83 +165,83
165 165 end
166 166 b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |wr|
167 167 wr.wrapper :form_check_wrapper, tag: 'div', class: 'form-check' do |bb|
168 168 bb.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
169 169 bb.use :label, class: 'form-check-label'
170 170 bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
171 171 bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
172 172 end
173 173 end
174 174 end
175 175
176 176 # horizontal input for radio buttons and check boxes
177 - config.wrappers :horizontal_collection, item_wrapper_class: 'form-check', tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
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|
178 178 b.use :html5
179 179 b.optional :readonly
180 - b.use :label, class: 'col-sm-3 form-control-label'
180 + b.use :label, class: 'col-sm-3 col-form-label pt-0'
181 181 b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
182 182 ba.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
183 183 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
184 184 ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
185 185 end
186 186 end
187 187
188 188 # horizontal input for inline radio buttons and check boxes
189 - config.wrappers :horizontal_collection_inline, item_wrapper_class: 'form-check form-check-inline', tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
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|
190 190 b.use :html5
191 191 b.optional :readonly
192 - b.use :label, class: 'col-sm-3 form-control-label'
192 + b.use :label, class: 'col-sm-3 col-form-label pt-0'
193 193 b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
194 194 ba.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
195 195 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
196 196 ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
197 197 end
198 198 end
199 199
200 200 # horizontal file input
201 201 config.wrappers :horizontal_file, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
202 202 b.use :html5
203 203 b.use :placeholder
204 204 b.optional :maxlength
205 205 b.optional :minlength
206 206 b.optional :readonly
207 - b.use :label, class: 'col-sm-3 form-control-label'
207 + b.use :label, class: 'col-sm-3 col-form-label'
208 208 b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
209 209 ba.use :input, error_class: 'is-invalid', valid_class: 'is-valid'
210 210 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
211 211 ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
212 212 end
213 213 end
214 214
215 215 # horizontal multi select
216 216 config.wrappers :horizontal_multi_select, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
217 217 b.use :html5
218 218 b.optional :readonly
219 - b.use :label, class: 'col-sm-3 control-label'
219 + b.use :label, class: 'col-sm-3 col-form-label'
220 220 b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
221 221 ba.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |bb|
222 222 bb.use :input, class: 'form-control mx-1', error_class: 'is-invalid', valid_class: 'is-valid'
223 223 end
224 224 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
225 225 ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
226 226 end
227 227 end
228 228
229 229 # horizontal range input
230 230 config.wrappers :horizontal_range, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
231 231 b.use :html5
232 232 b.use :placeholder
233 233 b.optional :readonly
234 234 b.optional :step
235 - b.use :label, class: 'col-sm-3 form-control-label'
235 + b.use :label, class: 'col-sm-3 col-form-label'
236 236 b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
237 237 ba.use :input, class: 'form-control-range', error_class: 'is-invalid', valid_class: 'is-valid'
238 238 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
239 239 ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
240 240 end
241 241 end
242 242
243 243
244 244 # inline forms
245 245 #
246 246 # inline default_wrapper
247 247 config.wrappers :inline_form, tag: 'span', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
@@ -251,168 +251,169
251 251 b.optional :minlength
252 252 b.optional :pattern
253 253 b.optional :min_max
254 254 b.optional :readonly
255 255 b.use :label, class: 'sr-only'
256 256
257 257 b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
258 258 b.use :error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
259 259 b.optional :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
260 260 end
261 261
262 262 # inline input for boolean
263 - config.wrappers :inline_boolean, tag: 'span', class: 'form-check flex-wrap justify-content-start mr-sm-2', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
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|
264 264 b.use :html5
265 265 b.optional :readonly
266 266 b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
267 267 b.use :label, class: 'form-check-label'
268 268 b.use :error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
269 269 b.optional :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
270 270 end
271 271
272 272
273 273 # bootstrap custom forms
274 274 #
275 275 # custom input for boolean
276 276 config.wrappers :custom_boolean, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
277 277 b.use :html5
278 278 b.optional :readonly
279 279 b.wrapper :form_check_wrapper, tag: 'div', class: 'custom-control custom-checkbox' do |bb|
280 280 bb.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
281 281 bb.use :label, class: 'custom-control-label'
282 282 bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
283 283 bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
284 284 end
285 285 end
286 286
287 + # custom input switch for boolean
287 288 config.wrappers :custom_boolean_switch, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
288 289 b.use :html5
289 290 b.optional :readonly
290 - b.wrapper :form_check_wrapper, tag: 'div', class: 'custom-control custom-checkbox-switch' do |bb|
291 + b.wrapper :form_check_wrapper, tag: 'div', class: 'custom-control custom-switch' do |bb|
291 292 bb.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
292 293 bb.use :label, class: 'custom-control-label'
293 294 bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
294 295 bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
295 296 end
296 297 end
297 298
298 299 # custom input for radio buttons and check boxes
299 - config.wrappers :custom_collection, item_wrapper_class: 'custom-control', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
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|
300 301 b.use :html5
301 302 b.optional :readonly
302 303 b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
303 304 ba.use :label_text
304 305 end
305 306 b.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
306 307 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
307 308 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
308 309 end
309 310
310 311 # custom input for inline radio buttons and check boxes
311 - config.wrappers :custom_collection_inline, item_wrapper_class: 'custom-control custom-control-inline', tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
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|
312 313 b.use :html5
313 314 b.optional :readonly
314 315 b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
315 316 ba.use :label_text
316 317 end
317 318 b.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
318 319 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
319 320 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
320 321 end
321 322
322 323 # custom file input
323 324 config.wrappers :custom_file, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
324 325 b.use :html5
325 326 b.use :placeholder
326 327 b.optional :maxlength
327 328 b.optional :minlength
328 329 b.optional :readonly
329 - b.use :label, class: 'form-control-label'
330 + b.use :label
330 331 b.wrapper :custom_file_wrapper, tag: 'div', class: 'custom-file' do |ba|
331 332 ba.use :input, class: 'custom-file-input', error_class: 'is-invalid', valid_class: 'is-valid'
332 333 ba.use :label, class: 'custom-file-label'
333 334 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
334 335 end
335 336 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
336 337 end
337 338
338 339 # custom multi select
339 340 config.wrappers :custom_multi_select, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
340 341 b.use :html5
341 342 b.optional :readonly
342 - b.use :label, class: 'form-control-label'
343 + b.use :label
343 344 b.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |ba|
344 345 ba.use :input, class: 'custom-select mx-1', error_class: 'is-invalid', valid_class: 'is-valid'
345 346 end
346 347 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
347 348 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
348 349 end
349 350
350 351 # custom range input
351 352 config.wrappers :custom_range, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
352 353 b.use :html5
353 354 b.use :placeholder
354 355 b.optional :readonly
355 356 b.optional :step
356 - b.use :label, class: 'form-control-label'
357 + b.use :label
357 358 b.use :input, class: 'custom-range', error_class: 'is-invalid', valid_class: 'is-valid'
358 359 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
359 360 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
360 361 end
361 362
362 363
363 364 # Input Group - custom component
364 365 # see example app and config at https://github.com/rafaelfranca/simple_form-bootstrap
365 366 # config.wrappers :input_group, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
366 367 # b.use :html5
367 368 # b.use :placeholder
368 369 # b.optional :maxlength
369 370 # b.optional :minlength
370 371 # b.optional :pattern
371 372 # b.optional :min_max
372 373 # b.optional :readonly
373 - # b.use :label, class: 'form-control-label'
374 + # b.use :label
374 375 # b.wrapper :input_group_tag, tag: 'div', class: 'input-group' do |ba|
375 376 # ba.optional :prepend
376 377 # ba.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
377 378 # ba.optional :append
378 379 # end
379 380 # b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
380 381 # b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
381 382 # end
382 383
383 384
384 385 # Floating Labels form
385 386 #
386 387 # floating labels default_wrapper
387 388 config.wrappers :floating_labels_form, tag: 'div', class: 'form-label-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
388 389 b.use :html5
389 390 b.use :placeholder
390 391 b.optional :maxlength
391 392 b.optional :minlength
392 393 b.optional :pattern
393 394 b.optional :min_max
394 395 b.optional :readonly
395 396 b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
396 - b.use :label, class: 'form-control-label'
397 + b.use :label
397 398 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
398 399 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
399 400 end
400 401
401 402 # custom multi select
402 403 config.wrappers :floating_labels_select, tag: 'div', class: 'form-label-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
403 404 b.use :html5
404 405 b.optional :readonly
405 - b.use :input, class: 'custom-select custom-select-lg', error_class: 'is-invalid', valid_class: 'is-valid'
406 - b.use :label, class: 'form-control-label'
406 + b.use :input, class: 'custom-select', error_class: 'is-invalid', valid_class: 'is-valid'
407 + b.use :label
407 408 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
408 409 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
409 410 end
410 411
411 412
412 413 # The default wrapper to be used by the FormBuilder.
413 414 config.default_wrapper = :vertical_form
414 415
415 416 # Custom wrappers for input types. This should be a hash containing an input
416 417 # type as key and the wrapper that will be used for all inputs with specified type.
417 418 config.wrapper_mappings = {
418 419 boolean: :vertical_boolean,
You need to be logged in to leave comments. Login now