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,36 +1,35
1 source 'https://rubygems.org'
1 source 'https://rubygems.org'
2 git_source(:github) { |repo| "https://github.com/#{repo}.git" }
2 git_source(:github) { |repo| "https://github.com/#{repo}.git" }
3
3
4 ruby '3.1.2'
4 ruby '3.1.2'
5
5
6 #rails
6 #rails
7 gem 'rails', '~>7.0'
7 gem 'rails', '~>7.0'
8
8
9 # The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]
9 # The original asset pipeline for Rails [https://github.com/rails/sprockets-rails]
10 gem "sprockets-rails"
10 gem "sprockets-rails"
11
11
12 - gem 'activerecord-session_store'
13 gem 'puma'
12 gem 'puma'
14
13
15 # Reduces boot times through caching; required in config/boot.rb
14 # Reduces boot times through caching; required in config/boot.rb
16 gem 'bootsnap', require: false
15 gem 'bootsnap', require: false
17
16
18 # Bundle edge Rails instead:
17 # Bundle edge Rails instead:
19 # gem 'rails', :git => 'git://github.com/rails/rails.git'
18 # gem 'rails', :git => 'git://github.com/rails/rails.git'
20
19
21 #---------------- database ---------------------
20 #---------------- database ---------------------
22 #the database
21 #the database
23 gem 'mysql2'
22 gem 'mysql2'
24 #for testing
23 #for testing
25 gem 'sqlite3'
24 gem 'sqlite3'
26 #gem 'rails-controller-testing'
25 #gem 'rails-controller-testing'
27 #for dumping database into yaml
26 #for dumping database into yaml
28 #gem 'yaml_db'
27 #gem 'yaml_db'
29
28
30
29
31 #------------- assset pipeline -----------------
30 #------------- assset pipeline -----------------
32 # Gems used only for assets and not required
31 # Gems used only for assets and not required
33 # in production environments by default.
32 # in production environments by default.
34 #sass-rails is depricated
33 #sass-rails is depricated
35 #gem 'sass-rails'
34 #gem 'sass-rails'
36 gem 'sassc-rails'
35 gem 'sassc-rails'
@@ -45,54 +45,48
45 rack-test (>= 0.6.3)
45 rack-test (>= 0.6.3)
46 rails-dom-testing (~> 2.0)
46 rails-dom-testing (~> 2.0)
47 rails-html-sanitizer (~> 1.0, >= 1.2.0)
47 rails-html-sanitizer (~> 1.0, >= 1.2.0)
48 actiontext (7.0.4)
48 actiontext (7.0.4)
49 actionpack (= 7.0.4)
49 actionpack (= 7.0.4)
50 activerecord (= 7.0.4)
50 activerecord (= 7.0.4)
51 activestorage (= 7.0.4)
51 activestorage (= 7.0.4)
52 activesupport (= 7.0.4)
52 activesupport (= 7.0.4)
53 globalid (>= 0.6.0)
53 globalid (>= 0.6.0)
54 nokogiri (>= 1.8.5)
54 nokogiri (>= 1.8.5)
55 actionview (7.0.4)
55 actionview (7.0.4)
56 activesupport (= 7.0.4)
56 activesupport (= 7.0.4)
57 builder (~> 3.1)
57 builder (~> 3.1)
58 erubi (~> 1.4)
58 erubi (~> 1.4)
59 rails-dom-testing (~> 2.0)
59 rails-dom-testing (~> 2.0)
60 rails-html-sanitizer (~> 1.1, >= 1.2.0)
60 rails-html-sanitizer (~> 1.1, >= 1.2.0)
61 activejob (7.0.4)
61 activejob (7.0.4)
62 activesupport (= 7.0.4)
62 activesupport (= 7.0.4)
63 globalid (>= 0.3.6)
63 globalid (>= 0.3.6)
64 activemodel (7.0.4)
64 activemodel (7.0.4)
65 activesupport (= 7.0.4)
65 activesupport (= 7.0.4)
66 activerecord (7.0.4)
66 activerecord (7.0.4)
67 activemodel (= 7.0.4)
67 activemodel (= 7.0.4)
68 activesupport (= 7.0.4)
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 activestorage (7.0.4)
69 activestorage (7.0.4)
76 actionpack (= 7.0.4)
70 actionpack (= 7.0.4)
77 activejob (= 7.0.4)
71 activejob (= 7.0.4)
78 activerecord (= 7.0.4)
72 activerecord (= 7.0.4)
79 activesupport (= 7.0.4)
73 activesupport (= 7.0.4)
80 marcel (~> 1.0)
74 marcel (~> 1.0)
81 mini_mime (>= 1.1.0)
75 mini_mime (>= 1.1.0)
82 activesupport (7.0.4)
76 activesupport (7.0.4)
83 concurrent-ruby (~> 1.0, >= 1.0.2)
77 concurrent-ruby (~> 1.0, >= 1.0.2)
84 i18n (>= 1.6, < 2)
78 i18n (>= 1.6, < 2)
85 minitest (>= 5.1)
79 minitest (>= 5.1)
86 tzinfo (~> 2.0)
80 tzinfo (~> 2.0)
87 addressable (2.8.1)
81 addressable (2.8.1)
88 public_suffix (>= 2.0.2, < 6.0)
82 public_suffix (>= 2.0.2, < 6.0)
89 ansi (1.5.0)
83 ansi (1.5.0)
90 autoprefixer-rails (10.4.7.0)
84 autoprefixer-rails (10.4.7.0)
91 execjs (~> 2)
85 execjs (~> 2)
92 bindex (0.8.1)
86 bindex (0.8.1)
93 bootsnap (1.13.0)
87 bootsnap (1.13.0)
94 msgpack (~> 1.2)
88 msgpack (~> 1.2)
95 bootstrap (5.2.1)
89 bootstrap (5.2.1)
96 autoprefixer-rails (>= 9.1.0)
90 autoprefixer-rails (>= 9.1.0)
97 popper_js (>= 2.11.6, < 3)
91 popper_js (>= 2.11.6, < 3)
98 sassc-rails (>= 2.0.0)
92 sassc-rails (>= 2.0.0)
@@ -124,80 +118,78
124 ffi (1.15.5)
118 ffi (1.15.5)
125 fuzzy-string-match (1.0.1)
119 fuzzy-string-match (1.0.1)
126 RubyInline (>= 3.8.6)
120 RubyInline (>= 3.8.6)
127 globalid (1.0.0)
121 globalid (1.0.0)
128 activesupport (>= 5.0)
122 activesupport (>= 5.0)
129 haml (5.2.2)
123 haml (5.2.2)
130 temple (>= 0.8.0)
124 temple (>= 0.8.0)
131 tilt
125 tilt
132 haml-rails (2.0.1)
126 haml-rails (2.0.1)
133 actionpack (>= 5.1)
127 actionpack (>= 5.1)
134 activesupport (>= 5.1)
128 activesupport (>= 5.1)
135 haml (>= 4.0.6, < 6.0)
129 haml (>= 4.0.6, < 6.0)
136 html2haml (>= 1.0.1)
130 html2haml (>= 1.0.1)
137 railties (>= 5.1)
131 railties (>= 5.1)
138 html2haml (2.2.0)
132 html2haml (2.2.0)
139 erubis (~> 2.7.0)
133 erubis (~> 2.7.0)
140 haml (>= 4.0, < 6)
134 haml (>= 4.0, < 6)
141 nokogiri (>= 1.6.0)
135 nokogiri (>= 1.6.0)
142 ruby_parser (~> 3.5)
136 ruby_parser (~> 3.5)
143 i18n (1.12.0)
137 i18n (1.12.0)
144 concurrent-ruby (~> 1.0)
138 concurrent-ruby (~> 1.0)
145 importmap-rails (1.1.5)
139 importmap-rails (1.1.5)
146 actionpack (>= 6.0.0)
140 actionpack (>= 6.0.0)
147 railties (>= 6.0.0)
141 railties (>= 6.0.0)
148 - in_place_editing (1.2.0)
149 jbuilder (2.11.5)
142 jbuilder (2.11.5)
150 actionview (>= 5.0.0)
143 actionview (>= 5.0.0)
151 activesupport (>= 5.0.0)
144 activesupport (>= 5.0.0)
152 jquery-rails (4.5.0)
145 jquery-rails (4.5.0)
153 rails-dom-testing (>= 1, < 3)
146 rails-dom-testing (>= 1, < 3)
154 railties (>= 4.2.0)
147 railties (>= 4.2.0)
155 thor (>= 0.14, < 2.0)
148 thor (>= 0.14, < 2.0)
156 listen (3.0.8)
149 listen (3.0.8)
157 rb-fsevent (~> 0.9, >= 0.9.4)
150 rb-fsevent (~> 0.9, >= 0.9.4)
158 rb-inotify (~> 0.9, >= 0.9.7)
151 rb-inotify (~> 0.9, >= 0.9.7)
159 loofah (2.19.0)
152 loofah (2.19.0)
160 crass (~> 1.0.2)
153 crass (~> 1.0.2)
161 nokogiri (>= 1.5.9)
154 nokogiri (>= 1.5.9)
162 mail (2.7.1)
155 mail (2.7.1)
163 mini_mime (>= 0.1.1)
156 mini_mime (>= 0.1.1)
164 marcel (1.0.2)
157 marcel (1.0.2)
165 material_icons (2.2.1)
158 material_icons (2.2.1)
166 railties (>= 3.2)
159 railties (>= 3.2)
167 matrix (0.4.2)
160 matrix (0.4.2)
168 method_source (1.0.0)
161 method_source (1.0.0)
169 mini_mime (1.1.2)
162 mini_mime (1.1.2)
170 minitest (5.16.3)
163 minitest (5.16.3)
171 minitest-reporters (1.5.0)
164 minitest-reporters (1.5.0)
172 ansi
165 ansi
173 builder
166 builder
174 minitest (>= 5.0)
167 minitest (>= 5.0)
175 ruby-progressbar
168 ruby-progressbar
176 momentjs-rails (2.29.4.1)
169 momentjs-rails (2.29.4.1)
177 railties (>= 3.1)
170 railties (>= 3.1)
178 msgpack (1.5.6)
171 msgpack (1.5.6)
179 - multi_json (1.15.0)
180 mysql2 (0.5.4)
172 mysql2 (0.5.4)
181 net-imap (0.2.3)
173 net-imap (0.2.3)
182 digest
174 digest
183 net-protocol
175 net-protocol
184 strscan
176 strscan
185 net-pop (0.1.1)
177 net-pop (0.1.1)
186 digest
178 digest
187 net-protocol
179 net-protocol
188 timeout
180 timeout
189 net-protocol (0.1.3)
181 net-protocol (0.1.3)
190 timeout
182 timeout
191 net-smtp (0.3.1)
183 net-smtp (0.3.1)
192 digest
184 digest
193 net-protocol
185 net-protocol
194 timeout
186 timeout
195 nio4r (2.5.8)
187 nio4r (2.5.8)
196 nokogiri (1.13.8-x86_64-linux)
188 nokogiri (1.13.8-x86_64-linux)
197 racc (~> 1.4)
189 racc (~> 1.4)
198 popper_js (2.11.6)
190 popper_js (2.11.6)
199 public_suffix (5.0.0)
191 public_suffix (5.0.0)
200 puma (5.6.5)
192 puma (5.6.5)
201 nio4r (~> 2.0)
193 nio4r (~> 2.0)
202 racc (1.6.0)
194 racc (1.6.0)
203 rack (2.2.4)
195 rack (2.2.4)
@@ -278,60 +270,58
278 tzinfo (2.0.5)
270 tzinfo (2.0.5)
279 concurrent-ruby (~> 1.0)
271 concurrent-ruby (~> 1.0)
280 web-console (4.2.0)
272 web-console (4.2.0)
281 actionview (>= 6.0.0)
273 actionview (>= 6.0.0)
282 activemodel (>= 6.0.0)
274 activemodel (>= 6.0.0)
283 bindex (>= 0.4.0)
275 bindex (>= 0.4.0)
284 railties (>= 6.0.0)
276 railties (>= 6.0.0)
285 webdrivers (5.1.0)
277 webdrivers (5.1.0)
286 nokogiri (~> 1.6)
278 nokogiri (~> 1.6)
287 rubyzip (>= 1.3.0)
279 rubyzip (>= 1.3.0)
288 selenium-webdriver (~> 4.0)
280 selenium-webdriver (~> 4.0)
289 websocket (1.2.9)
281 websocket (1.2.9)
290 websocket-driver (0.7.5)
282 websocket-driver (0.7.5)
291 websocket-extensions (>= 0.1.0)
283 websocket-extensions (>= 0.1.0)
292 websocket-extensions (0.1.5)
284 websocket-extensions (0.1.5)
293 xpath (3.2.0)
285 xpath (3.2.0)
294 nokogiri (~> 1.8)
286 nokogiri (~> 1.8)
295 zeitwerk (2.6.0)
287 zeitwerk (2.6.0)
296
288
297 PLATFORMS
289 PLATFORMS
298 x86_64-linux
290 x86_64-linux
299
291
300 DEPENDENCIES
292 DEPENDENCIES
301 ace-rails-ap
293 ace-rails-ap
302 - activerecord-session_store
303 best_in_place!
294 best_in_place!
304 bootsnap
295 bootsnap
305 bootstrap (~> 5.2)
296 bootstrap (~> 5.2)
306 byebug
297 byebug
307 capybara
298 capybara
308 coffee-rails
299 coffee-rails
309 fuzzy-string-match
300 fuzzy-string-match
310 haml
301 haml
311 haml-rails
302 haml-rails
312 importmap-rails (~> 1.1)
303 importmap-rails (~> 1.1)
313 - in_place_editing
314 jbuilder
304 jbuilder
315 jquery-rails
305 jquery-rails
316 listen (>= 3.0.5, < 3.2)
306 listen (>= 3.0.5, < 3.2)
317 mail
307 mail
318 material_icons
308 material_icons
319 minitest-reporters
309 minitest-reporters
320 momentjs-rails
310 momentjs-rails
321 mysql2
311 mysql2
322 puma
312 puma
323 rails (~> 7.0)
313 rails (~> 7.0)
324 rdiscount
314 rdiscount
325 rouge
315 rouge
326 sassc-rails
316 sassc-rails
327 selenium-webdriver
317 selenium-webdriver
328 simple_form
318 simple_form
329 spring
319 spring
330 spring-watcher-listen (~> 2.0.0)
320 spring-watcher-listen (~> 2.0.0)
331 sprockets-rails
321 sprockets-rails
332 sqlite3
322 sqlite3
333 web-console (>= 3.3.0)
323 web-console (>= 3.3.0)
334 webdrivers
324 webdrivers
335
325
336 RUBY VERSION
326 RUBY VERSION
337 ruby 3.1.2p20
327 ruby 3.1.2p20
@@ -5,52 +5,44
5 label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
5 label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
6 input.trigger('fileselect', [numFiles, label]);
6 input.trigger('fileselect', [numFiles, label]);
7 });
7 });
8
8
9 $(function() {
9 $(function() {
10 var e;
10 var e;
11 $(".select2").select2({
11 $(".select2").select2({
12 theme: "bootstrap-5",
12 theme: "bootstrap-5",
13 //selectionCssClass: "select2--small",
13 //selectionCssClass: "select2--small",
14 //dropdownCssClass: "select2--small",
14 //dropdownCssClass: "select2--small",
15 });
15 });
16
16
17 $('.btn-file :file').on('fileselect', function(event, numFiles, label) {
17 $('.btn-file :file').on('fileselect', function(event, numFiles, label) {
18 var input, log;
18 var input, log;
19 input = $(this).parents('.input-group').find(':text');
19 input = $(this).parents('.input-group').find(':text');
20 log = numFiles > 1 ? numFiles + ' files selected' : label;
20 log = numFiles > 1 ? numFiles + ' files selected' : label;
21 if (input.length) {
21 if (input.length) {
22 input.val(log);
22 input.val(log);
23 } else {
23 } else {
24 if (log) {
24 if (log) {
25 alert(log);
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 $('.ajax-toggle').on('click', function(event) {
29 $('.ajax-toggle').on('click', function(event) {
38 var target;
30 var target;
39 target = $(event.target);
31 target = $(event.target);
40 target.removeClass('btn-default');
32 target.removeClass('btn-default');
41 target.removeClass('btn-success');
33 target.removeClass('btn-success');
42 target.addClass('btn-warning');
34 target.addClass('btn-warning');
43 target.text('...');
35 target.text('...');
44 });
36 });
45 if ($("#editor").length > 0) {
37 if ($("#editor").length > 0) {
46 e = ace.edit("editor");
38 e = ace.edit("editor");
47 e.setTheme('ace/theme/merbivore');
39 e.setTheme('ace/theme/merbivore');
48 e.getSession().setTabSize(2);
40 e.getSession().setTabSize(2);
49 e.getSession().setUseSoftTabs(true);
41 e.getSession().setUseSoftTabs(true);
50 }
42 }
51
43
52 //jQuery(".best_in_place").best_in_place();
44 //jQuery(".best_in_place").best_in_place();
53 });
45 });
54
46
55 // ---
47 // ---
56 // generated by coffee-script 1.9.2
48 // generated by coffee-script 1.9.2
@@ -8,26 +8,27
8 = javascript_include_tag :my_app
8 = javascript_include_tag :my_app
9 -# = javascript_import_module_tag('prepend_jquery')
9 -# = javascript_import_module_tag('prepend_jquery')
10 = javascript_importmap_tags
10 = javascript_importmap_tags
11 = content_for :header
11 = content_for :header
12 = yield :head
12 = yield :head
13 -# %link{href:"https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/css/bootstrap.min.css",rel:"stylesheet",integrity:"sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT",crossorigin:"anonymous"}
13 -# %link{href:"https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/css/bootstrap.min.css",rel:"stylesheet",integrity:"sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT",crossorigin:"anonymous"}
14 -# %script{src:"https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js",integrity:"sha384-oBqDVmMz9ATKxIep9tiCxS/Z9fNfEXiDAYTujMAeBAsjFuCZSmKbSSUnQlmh/jp3",crossorigin:"anonymous"}
14 -# %script{src:"https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js",integrity:"sha384-oBqDVmMz9ATKxIep9tiCxS/Z9fNfEXiDAYTujMAeBAsjFuCZSmKbSSUnQlmh/jp3",crossorigin:"anonymous"}
15 -# %script{src:"https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/js/bootstrap.bundle.min.js",integrity:"sha384-7VPbUDkoPSGFnVtYi0QogXtr74QeVeeIs99Qfg5YCF+TidwNdjvaKZX19NZ/e6oz",crossorigin:"anonymous"}
15 -# %script{src:"https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/js/bootstrap.bundle.min.js",integrity:"sha384-7VPbUDkoPSGFnVtYi0QogXtr74QeVeeIs99Qfg5YCF+TidwNdjvaKZX19NZ/e6oz",crossorigin:"anonymous"}
16
16
17 <link rel="preconnect" href="https://fonts.googleapis.com">
17 <link rel="preconnect" href="https://fonts.googleapis.com">
18 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
18 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
19 -#
19 -#
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">
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 <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">
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 <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">
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 <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">
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 <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">
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 <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">
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 %body
27 %body
28 - unless local_assigns[:skip_header]
28 - unless local_assigns[:skip_header]
29 = render 'layouts/header'
29 = render 'layouts/header'
30
30
31 /= content_tag(:p,flash[:notice],class: 'alert alert-success') if flash[:notice]!=nil
31 /= content_tag(:p,flash[:notice],class: 'alert alert-success') if flash[:notice]!=nil
32 + .container-fluid
32 = flash_messages
33 = flash_messages
33 = yield
34 = yield
@@ -1,43 +1,88
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 %br/
45 %br/
3
46
4 - if !@hidelogin
47 - if !@hidelogin
5 =t 'login.message'
48 =t 'login.message'
6 %br/
49 %br/
7 %br/
50 %br/
8
51
9 - if flash[:notice]
52 - if flash[:notice]
10 %hr/
53 %hr/
11 %b= flash[:notice]
54 %b= flash[:notice]
12 %hr/
55 %hr/
13
56
14 %div{ :style => "border: solid 1px gray; padding: 4px; background: #eeeeff;"}
57 %div{ :style => "border: solid 1px gray; padding: 4px; background: #eeeeff;"}
15 = form_tag login_login_path, {class: 'form-horizontal'} do
58 = form_tag login_login_path, {class: 'form-horizontal'} do
16 .form-group
59 .form-group
17 =label_tag :login, "Login",class: 'col-sm-3 control-label'
60 =label_tag :login, "Login",class: 'col-sm-3 control-label'
18 .col-sm-9
61 .col-sm-9
19 =text_field_tag :login, nil, class: 'form-control'
62 =text_field_tag :login, nil, class: 'form-control'
20 .form-group
63 .form-group
21 =label_tag :password, "Password", class: 'col-sm-3 control-label'
64 =label_tag :password, "Password", class: 'col-sm-3 control-label'
22 .col-sm-9
65 .col-sm-9
23 =password_field_tag :password, nil, class: 'form-control'
66 =password_field_tag :password, nil, class: 'form-control'
24 - unless GraderConfiguration['right.bypass_agreement']
67 - unless GraderConfiguration['right.bypass_agreement']
25 .form-group
68 .form-group
26 .col-sm-offset-3.col-sm-9
69 .col-sm-offset-3.col-sm-9
27 .checkbox
70 .checkbox
28 %label
71 %label
29 = check_box_tag 'accept_agree'
72 = check_box_tag 'accept_agree'
30 ΰΈ’ΰΈ­ΰΈ‘ΰΈ£ΰΈ±ΰΈšΰΈ‚ΰΉ‰ΰΈ­ΰΈ•ΰΈΰΈ₯ΰΈ‡ΰΈΰΈ²ΰΈ£ΰΉƒΰΈŠΰΉ‰ΰΈ‡ΰΈ²ΰΈ™
73 ΰΈ’ΰΈ­ΰΈ‘ΰΈ£ΰΈ±ΰΈšΰΈ‚ΰΉ‰ΰΈ­ΰΈ•ΰΈΰΈ₯ΰΈ‡ΰΈΰΈ²ΰΈ£ΰΉƒΰΈŠΰΉ‰ΰΈ‡ΰΈ²ΰΈ™
31
74
32 .form-group
75 .form-group
33 .col-sm-offset-3.col-sm-9
76 .col-sm-offset-3.col-sm-9
34 = submit_tag t('login.login_submit'), class: 'btn btn-primary'
77 = submit_tag t('login.login_submit'), class: 'btn btn-primary'
78 + - else
79 +
35 %br/
80 %br/
36
81
37 - if GraderConfiguration['system.online_registration']
82 - if GraderConfiguration['system.online_registration']
38 =t 'login.participation'
83 =t 'login.participation'
39 %b
84 %b
40 = "#{t 'login.please'} "
85 = "#{t 'login.please'} "
41 = link_to "#{t 'login.register'}", :controller => :users, :action => :new
86 = link_to "#{t 'login.register'}", :controller => :users, :action => :new
42 %br/
87 %br/
43 = link_to "#{t 'login.forget_password'}", :controller => :users, :action => :forget
88 = link_to "#{t 'login.forget_password'}", :controller => :users, :action => :forget
@@ -3,71 +3,70
3 .hof_language { color: green; font-style: italic; }
3 .hof_language { color: green; font-style: italic; }
4 .hof_value { color: deeppink;font-style: italic; }
4 .hof_value { color: deeppink;font-style: italic; }
5 .info_param { font-weight: bold;text-align: right; }
5 .info_param { font-weight: bold;text-align: right; }
6 .tooltip {
6 .tooltip {
7 font-family: Verdana,sans-serif;
7 font-family: Verdana,sans-serif;
8 font-weight: normal;
8 font-weight: normal;
9 text-align: left;
9 text-align: left;
10 font-size: 1.0em;
10 font-size: 1.0em;
11 color: black;
11 color: black;
12 line-height: 1.1;
12 line-height: 1.1;
13 display: none;
13 display: none;
14 min-width: 20em;
14 min-width: 20em;
15 position: absolute;
15 position: absolute;
16 left: 25px;
16 left: 25px;
17 bottom: 5px;
17 bottom: 5px;
18 border: 1px solid;
18 border: 1px solid;
19 padding: 5px;
19 padding: 5px;
20 background-color: #FFF;
20 background-color: #FFF;
21 word-wrap: break-word;
21 word-wrap: break-word;
22 z-index: 9999;
22 z-index: 9999;
23 overflow: auto;
23 overflow: auto;
24 }
24 }
25
25
26
26
27 - .container-fluid
27 + .row.mb-3
28 - .row
29 .col-md-8
28 .col-md-8
30 .card
29 .card
31 .card-body
30 .card-body
32 %h2.card-title Submission History
31 %h2.card-title Submission History
33 %canvas#chart{height: '50px'}
32 %canvas#chart{height: '50px'}
34
33
35 .col-md-4
34 .col-md-4
36 .card
35 .card
37 .card-body
36 .card-body
38 %h2.card-title General Info
37 %h2.card-title General Info
39 .row
38 .row
40 .col-sm-6
39 .col-sm-6
41 Subs
40 Subs
42 .col-sm-6
41 .col-sm-6
43 = @summary[:count]
42 = @summary[:count]
44 .row
43 .row
45 .col-sm-6
44 .col-sm-6
46 Solved/Attempted User
45 Solved/Attempted User
47 .col-sm-6
46 .col-sm-6
48 #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
47 #{@summary[:solve]}/#{@summary[:attempt]} (#{(@summary[:solve]*100.0/@summary[:attempt]).round(1)}%)
49 - .row
48 + .row.mb-3
50 .col-md-4
49 .col-md-4
51 .card
50 .card
52 .card-body
51 .card-body
53 %h2.card-title Model submission
52 %h2.card-title Model submission
54 %table.table.table-hover
53 %table.table.table-hover
55 %thead
54 %thead
56 %tr
55 %tr
57 %th #Sub (lang)
56 %th #Sub (lang)
58 %th Author
57 %th Author
59 %tbody
58 %tbody
60 - @model_subs.each do |sub|
59 - @model_subs.each do |sub|
61 %tr
60 %tr
62 %td
61 %td
63 = link_to "##{sub.id}", submission_path(sub)
62 = link_to "##{sub.id}", submission_path(sub)
64 = "(#{sub.language.pretty_name})"
63 = "(#{sub.language.pretty_name})"
65 %td= sub.user.full_name
64 %td= sub.user.full_name
66 .col-md-8
65 .col-md-8
67 - if @best
66 - if @best
68 .card
67 .card
69 .card-body
68 .card-body
70 %h2.card-title Top Submissions
69 %h2.card-title Top Submissions
71 %table.table.table-hover
70 %table.table.table-hover
72 %thead
71 %thead
73 %tr
72 %tr
@@ -1,30 +1,20
1
1
2 /- if params[:id]
2 /- if params[:id]
3 / %h1 Tasks Hall of Fame
3 / %h1 Tasks Hall of Fame
4 / = link_to('[back to All-Time Hall of Fame]', action: 'problem_hof', id: nil )
4 / = link_to('[back to All-Time Hall of Fame]', action: 'problem_hof', id: nil )
5 /- else
5 /- else
6 / %h1 All-Time Hall of Fame
6 / %h1 All-Time Hall of Fame
7
7
8 - .panel.panel-info
8 + .row.mb-5
9 - .panel-heading
9 + .col-md-6
10 - Select Task
10 + = render 'problem_chooser', {problems: @problems, selected_problem: @problem, target_url_method: :problem_hof_report_path}
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 -
20
11
21 - unless params[:id]
12 - unless params[:id]
22 - /=render partial: 'all_time_hof'
23 Please select a problem.
13 Please select a problem.
24 - else
14 - else
25 - %h1
15 + %h1.mt-3
26 [#{Problem.find(params[:id]).name}] #{Problem.find(params[:id]).full_name}
16 [#{Problem.find(params[:id]).name}] #{Problem.find(params[:id]).full_name}
27 - if @current_user.has_role?('ta')
17 - if @current_user.has_role?('ta')
28 %a{href:stat_problem_path(@problem)} (stat)
18 %a{href:stat_problem_path(@problem)} (stat)
29 =render partial: 'task_hof'
19 =render partial: 'task_hof'
30
20
@@ -1,31 +1,19
1 - .card.border-info.mb-2
1 + = render 'problem_chooser', {problems: @problems, selected_problem: @problem, target_url_method: :problem_submissions_path}
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
14
2
15 - if @problem!=nil
3 - if @problem!=nil
16 %h2= "Task: #{@problem.full_name} (#{@problem.name})"
4 %h2= "Task: #{@problem.full_name} (#{@problem.name})"
17
5
18 - if @submissions!=nil
6 - if @submissions!=nil
19 - if @submissions.length>0
7 - if @submissions.length>0
20 %table.table
8 %table.table
21 %thead
9 %thead
22 %th No.
10 %th No.
23 %th.text-right #
11 %th.text-right #
24 %th At
12 %th At
25 %th Source
13 %th Source
26 %th Result
14 %th Result
27 %th{:width => "300px"} Compiler message
15 %th{:width => "300px"} Compiler message
28 %th
16 %th
29 = render :partial => 'submission', :collection => @submissions
17 = render :partial => 'submission', :collection => @submissions
30 - else
18 - else
31 No submission
19 No submission
@@ -1,47 +1,47
1 %h1 Users
1 %h1 Users
2
2
3 - .panel.panel-primary
3 + .card.border-primary
4 - .panel-title.panel-heading
4 + .card-header.text-bg-primary.border-primary
5 Quick Add
5 Quick Add
6 - .panel-body
6 + .card-body
7 - = form_tag( {method: 'post'}, {class: 'form-inline'}) do
7 + = form_with url: 'asd', class: 'row row-cols-lg-auto g-3 align-items-center' do |f|
8 - .form-group
8 + .col-12
9 - = label_tag 'user_login', 'Login'
9 + = f.label 'user_login', 'Login'
10 - = text_field 'user', 'login', :size => 10,class: 'form-control'
10 + = f.text_field 'login', :size => 10,class: 'form-control'
11 .form-group
11 .form-group
12 - = label_tag 'user_full_name', 'Full Name'
12 + = f.label 'user_full_name', 'Full Name'
13 - = text_field 'user', 'full_name', :size => 10,class: 'form-control'
13 + = f.text_field 'full_name', :size => 10,class: 'form-control'
14 .form-group
14 .form-group
15 - = label_tag 'user_password', 'Password'
15 + = f.label 'user_password', 'Password'
16 - = text_field 'user', 'password', :size => 10,class: 'form-control'
16 + = f.text_field 'password', :size => 10,class: 'form-control'
17 .form-group
17 .form-group
18 - = label_tag 'user_password_confirmation', 'Confirm'
18 + = f.label 'user_password_confirmation', 'Confirm'
19 - = text_field 'user', 'password_confirmation', :size => 10,class: 'form-control'
19 + = f.text_field 'password_confirmation', :size => 10,class: 'form-control'
20 .form-group
20 .form-group
21 - = label_tag 'user_email', 'email'
21 + = f.label 'user_email', 'email'
22 - = text_field 'user', 'email', :size => 10,class: 'form-control'
22 + = f.text_field 'email', :size => 10,class: 'form-control'
23 - =submit_tag "Create", class: 'btn btn-primary'
23 + =submit_tag "Create", class: 'btn btn-primary align-items-bottom'
24
24
25 .panel.panel-primary
25 .panel.panel-primary
26 .panel-title.panel-heading
26 .panel-title.panel-heading
27 Import from site management
27 Import from site management
28 .panel-body
28 .panel-body
29 = form_tag({:action => 'import'}, :multipart => true,class: 'form form-inline') do
29 = form_tag({:action => 'import'}, :multipart => true,class: 'form form-inline') do
30 .form-group
30 .form-group
31 = label_tag :file, 'File:'
31 = label_tag :file, 'File:'
32 .input-group
32 .input-group
33 %span.input-group-btn
33 %span.input-group-btn
34 %span.btn.btn-default.btn-file
34 %span.btn.btn-default.btn-file
35 Browse
35 Browse
36 = file_field_tag 'file'
36 = file_field_tag 'file'
37 = text_field_tag '' , nil, {readonly: true, class: 'form-control'}
37 = text_field_tag '' , nil, {readonly: true, class: 'form-control'}
38 = submit_tag 'Submit', class: 'btn btn-default'
38 = submit_tag 'Submit', class: 'btn btn-default'
39
39
40
40
41 %p
41 %p
42 = link_to '+ New user', { :action => 'new' }, { class: 'btn btn-success '}
42 = link_to '+ New user', { :action => 'new' }, { class: 'btn btn-success '}
43 = link_to '+ New list of users', { :action => 'new_list' }, { class: 'btn btn-success '}
43 = link_to '+ New list of users', { :action => 'new_list' }, { class: 'btn btn-success '}
44 = link_to 'Bulk Manage', { action: :bulk_manage} , { class: 'btn btn-default btn-info'}
44 = link_to 'Bulk Manage', { action: :bulk_manage} , { class: 'btn btn-default btn-info'}
45 = link_to 'View administrators',{ :action => 'admin'}, { class: 'btn btn-default '}
45 = link_to 'View administrators',{ :action => 'admin'}, { class: 'btn btn-default '}
46 = link_to 'Random passwords',{ :action => 'random_all_passwords'}, { class: 'btn btn-default '}
46 = link_to 'Random passwords',{ :action => 'random_all_passwords'}, { class: 'btn btn-default '}
47 = link_to 'View active users',{ :action => 'active'}, { class: 'btn btn-default '}
47 = link_to 'View active users',{ :action => 'active'}, { class: 'btn btn-default '}
@@ -1,29 +1,29
1 # frozen_string_literal: true
1 # frozen_string_literal: true
2 #
2 #
3 # Uncomment this and change the path if necessary to include your own
3 # Uncomment this and change the path if necessary to include your own
4 # components.
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 # more about custom components.
6 # more about custom components.
7 # Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
7 # Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
8 #
8 #
9 # Use this setup block to configure all options available in SimpleForm.
9 # Use this setup block to configure all options available in SimpleForm.
10 SimpleForm.setup do |config|
10 SimpleForm.setup do |config|
11 # Wrappers are used by the form builder to generate a
11 # Wrappers are used by the form builder to generate a
12 # complete input. You can remove any component from the
12 # complete input. You can remove any component from the
13 # wrapper, change the order or even add your own to the
13 # wrapper, change the order or even add your own to the
14 # stack. The options given below are used to wrap the
14 # stack. The options given below are used to wrap the
15 # whole input.
15 # whole input.
16 config.wrappers :default, class: :input,
16 config.wrappers :default, class: :input,
17 hint_class: :field_with_hint, error_class: :field_with_errors, valid_class: :field_without_errors do |b|
17 hint_class: :field_with_hint, error_class: :field_with_errors, valid_class: :field_without_errors do |b|
18 ## Extensions enabled by default
18 ## Extensions enabled by default
19 # Any of these extensions can be disabled for a
19 # Any of these extensions can be disabled for a
20 # given input by passing: `f.input EXTENSION_NAME => false`.
20 # given input by passing: `f.input EXTENSION_NAME => false`.
21 # You can make any of these extensions optional by
21 # You can make any of these extensions optional by
22 # renaming `b.use` to `b.optional`.
22 # renaming `b.use` to `b.optional`.
23
23
24 # Determines whether to use HTML5 (:email, :url, ...)
24 # Determines whether to use HTML5 (:email, :url, ...)
25 # and required attributes
25 # and required attributes
26 b.use :html5
26 b.use :html5
27
27
28 # Calculates placeholders automatically from I18n
28 # Calculates placeholders automatically from I18n
29 # You can also pass a string as f.input placeholder: "Placeholder"
29 # You can also pass a string as f.input placeholder: "Placeholder"
@@ -108,51 +108,48
108
108
109 # How the label text should be generated altogether with the required text.
109 # How the label text should be generated altogether with the required text.
110 # config.label_text = lambda { |label, required, explicit_label| "#{required} #{label}" }
110 # config.label_text = lambda { |label, required, explicit_label| "#{required} #{label}" }
111
111
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 overriden
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
119 # You can define which elements should obtain additional classes
119 # You can define which elements should obtain additional classes
120 # config.generate_additional_classes_for = [:wrapper, :label, :input]
120 # config.generate_additional_classes_for = [:wrapper, :label, :input]
121
121
122 # Whether attributes are required by default (or not). Default is true.
122 # Whether attributes are required by default (or not). Default is true.
123 # config.required_by_default = true
123 # config.required_by_default = true
124
124
125 # Tell browsers whether to use the native HTML5 validations (novalidate form option).
125 # Tell browsers whether to use the native HTML5 validations (novalidate form option).
126 # These validations are enabled in SimpleForm's internal config but disabled by default
126 # These validations are enabled in SimpleForm's internal config but disabled by default
127 # in this configuration, which is recommended due to some quirks from different browsers.
127 # in this configuration, which is recommended due to some quirks from different browsers.
128 # To stop SimpleForm from generating the novalidate option, enabling the HTML5 validations,
128 # To stop SimpleForm from generating the novalidate option, enabling the HTML5 validations,
129 # change this configuration to true.
129 # change this configuration to true.
130 config.browser_validations = false
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 # Custom mappings for input types. This should be a hash containing a regexp
132 # Custom mappings for input types. This should be a hash containing a regexp
136 # to match as key, and the input type that will be used when the field name
133 # to match as key, and the input type that will be used when the field name
137 # matches the regexp as value.
134 # matches the regexp as value.
138 # config.input_mappings = { /count/ => :integer }
135 # config.input_mappings = { /count/ => :integer }
139
136
140 # Custom wrappers for input types. This should be a hash containing an input
137 # Custom wrappers for input types. This should be a hash containing an input
141 # type as key and the wrapper that will be used for all inputs with specified type.
138 # type as key and the wrapper that will be used for all inputs with specified type.
142 # config.wrapper_mappings = { string: :prepend }
139 # config.wrapper_mappings = { string: :prepend }
143
140
144 # Namespaces where SimpleForm should look for custom input classes that
141 # Namespaces where SimpleForm should look for custom input classes that
145 # override default inputs.
142 # override default inputs.
146 # config.custom_inputs_namespaces << "CustomInputs"
143 # config.custom_inputs_namespaces << "CustomInputs"
147
144
148 # Default priority for time_zone inputs.
145 # Default priority for time_zone inputs.
149 # config.time_zone_priority = nil
146 # config.time_zone_priority = nil
150
147
151 # Default priority for country inputs.
148 # Default priority for country inputs.
152 # config.country_priority = nil
149 # config.country_priority = nil
153
150
154 # When false, do not use translations for labels.
151 # When false, do not use translations for labels.
155 # config.translate_labels = true
152 # config.translate_labels = true
156
153
157 # Automatically discover new inputs in Rails' autoload path.
154 # Automatically discover new inputs in Rails' autoload path.
158 # config.inputs_discovery = true
155 # config.inputs_discovery = true
@@ -1,143 +1,143
1 # frozen_string_literal: true
1 # frozen_string_literal: true
2
2
3 # Please do not make direct changes to this file!
3 # Please do not make direct changes to this file!
4 # This generator is maintained by the community around simple_form-bootstrap:
4 # This generator is maintained by the community around simple_form-bootstrap:
5 # https://github.com/rafaelfranca/simple_form-bootstrap
5 # https://github.com/rafaelfranca/simple_form-bootstrap
6 # All future development, tests, and organization should happen there.
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 # Uncomment this and change the path if necessary to include your own
9 # Uncomment this and change the path if necessary to include your own
10 # components.
10 # components.
11 - # See https://github.com/plataformatec/simple_form#custom-components
11 + # See https://github.com/heartcombo/simple_form#custom-components
12 # to know more about custom components.
12 # to know more about custom components.
13 # Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
13 # Dir[Rails.root.join('lib/components/**/*.rb')].each { |f| require f }
14
14
15 # Use this setup block to configure all options available in SimpleForm.
15 # Use this setup block to configure all options available in SimpleForm.
16 SimpleForm.setup do |config|
16 SimpleForm.setup do |config|
17 # Default class for buttons
17 # Default class for buttons
18 config.button_class = 'btn'
18 config.button_class = 'btn'
19
19
20 # Define the default class of the input wrapper of the boolean input.
20 # Define the default class of the input wrapper of the boolean input.
21 config.boolean_label_class = 'form-check-label'
21 config.boolean_label_class = 'form-check-label'
22
22
23 # How the label text should be generated altogether with the required text.
23 # How the label text should be generated altogether with the required text.
24 config.label_text = lambda { |label, required, explicit_label| "#{label} #{required}" }
24 config.label_text = lambda { |label, required, explicit_label| "#{label} #{required}" }
25
25
26 # Define the way to render check boxes / radio buttons with labels.
26 # Define the way to render check boxes / radio buttons with labels.
27 config.boolean_style = :inline
27 config.boolean_style = :inline
28
28
29 # You can wrap each item in a collection of radio/check boxes with a tag
29 # You can wrap each item in a collection of radio/check boxes with a tag
30 config.item_wrapper_tag = :div
30 config.item_wrapper_tag = :div
31
31
32 # Defines if the default input wrapper class should be included in radio
32 # Defines if the default input wrapper class should be included in radio
33 # collection wrappers.
33 # collection wrappers.
34 config.include_default_input_wrapper_class = false
34 config.include_default_input_wrapper_class = false
35
35
36 # CSS class to add for error notification helper.
36 # CSS class to add for error notification helper.
37 config.error_notification_class = 'alert alert-danger'
37 config.error_notification_class = 'alert alert-danger'
38
38
39 # Method used to tidy up errors. Specify any Rails Array method.
39 # Method used to tidy up errors. Specify any Rails Array method.
40 # :first lists the first message for each field.
40 # :first lists the first message for each field.
41 # :to_sentence to list all errors for each field.
41 # :to_sentence to list all errors for each field.
42 config.error_method = :to_sentence
42 config.error_method = :to_sentence
43
43
44 # add validation classes to `input_field`
44 # add validation classes to `input_field`
45 config.input_field_error_class = 'is-invalid'
45 config.input_field_error_class = 'is-invalid'
46 config.input_field_valid_class = 'is-valid'
46 config.input_field_valid_class = 'is-valid'
47
47
48
48
49 # vertical forms
49 # vertical forms
50 #
50 #
51 # vertical default_wrapper
51 # 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|
52 config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
53 b.use :html5
53 b.use :html5
54 b.use :placeholder
54 b.use :placeholder
55 b.optional :maxlength
55 b.optional :maxlength
56 b.optional :minlength
56 b.optional :minlength
57 b.optional :pattern
57 b.optional :pattern
58 b.optional :min_max
58 b.optional :min_max
59 b.optional :readonly
59 b.optional :readonly
60 - b.use :label, class: 'form-control-label'
60 + b.use :label
61 b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
61 b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
62 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
62 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
63 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
63 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
64 end
64 end
65
65
66 # vertical input for boolean
66 # 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|
67 config.wrappers :vertical_boolean, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
68 b.use :html5
68 b.use :html5
69 b.optional :readonly
69 b.optional :readonly
70 b.wrapper :form_check_wrapper, tag: 'div', class: 'form-check' do |bb|
70 b.wrapper :form_check_wrapper, tag: 'div', class: 'form-check' do |bb|
71 bb.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
71 bb.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
72 bb.use :label, class: 'form-check-label'
72 bb.use :label, class: 'form-check-label'
73 bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
73 bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
74 bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
74 bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
75 end
75 end
76 end
76 end
77
77
78 # vertical input for radio buttons and check boxes
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 b.use :html5
80 b.use :html5
81 b.optional :readonly
81 b.optional :readonly
82 b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
82 b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
83 ba.use :label_text
83 ba.use :label_text
84 end
84 end
85 b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
85 b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
86 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
86 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
87 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
87 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
88 end
88 end
89
89
90 # vertical input for inline radio buttons and check boxes
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 b.use :html5
92 b.use :html5
93 b.optional :readonly
93 b.optional :readonly
94 b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
94 b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
95 ba.use :label_text
95 ba.use :label_text
96 end
96 end
97 b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
97 b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
98 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
98 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
99 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
99 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
100 end
100 end
101
101
102 # vertical file input
102 # 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|
103 config.wrappers :vertical_file, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
104 b.use :html5
104 b.use :html5
105 b.use :placeholder
105 b.use :placeholder
106 b.optional :maxlength
106 b.optional :maxlength
107 b.optional :minlength
107 b.optional :minlength
108 b.optional :readonly
108 b.optional :readonly
109 b.use :label
109 b.use :label
110 b.use :input, class: 'form-control-file', error_class: 'is-invalid', valid_class: 'is-valid'
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 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
112 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
113 end
113 end
114
114
115 # vertical multi select
115 # 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|
116 config.wrappers :vertical_multi_select, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
117 b.use :html5
117 b.use :html5
118 b.optional :readonly
118 b.optional :readonly
119 - b.use :label, class: 'form-control-label'
119 + b.use :label
120 b.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |ba|
120 b.wrapper tag: 'div', 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'
121 ba.use :input, class: 'form-control mx-1', error_class: 'is-invalid', valid_class: 'is-valid'
122 end
122 end
123 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
123 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
124 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
124 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
125 end
125 end
126
126
127 # vertical range input
127 # 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|
128 config.wrappers :vertical_range, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
129 b.use :html5
129 b.use :html5
130 b.use :placeholder
130 b.use :placeholder
131 b.optional :readonly
131 b.optional :readonly
132 b.optional :step
132 b.optional :step
133 b.use :label
133 b.use :label
134 b.use :input, class: 'form-control-range', error_class: 'is-invalid', valid_class: 'is-valid'
134 b.use :input, class: 'form-control-range', error_class: 'is-invalid', valid_class: 'is-valid'
135 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
135 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
136 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
136 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
137 end
137 end
138
138
139
139
140 # horizontal forms
140 # horizontal forms
141 #
141 #
142 # horizontal default_wrapper
142 # 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|
143 config.wrappers :horizontal_form, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
@@ -153,278 +153,279
153 ba.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
153 ba.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
154 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
154 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
155 ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
155 ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
156 end
156 end
157 end
157 end
158
158
159 # horizontal input for boolean
159 # 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|
160 config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
161 b.use :html5
161 b.use :html5
162 b.optional :readonly
162 b.optional :readonly
163 b.wrapper tag: 'label', class: 'col-sm-3' do |ba|
163 b.wrapper tag: 'label', class: 'col-sm-3' do |ba|
164 ba.use :label_text
164 ba.use :label_text
165 end
165 end
166 b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |wr|
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|
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'
168 bb.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
169 bb.use :label, class: 'form-check-label'
169 bb.use :label, class: 'form-check-label'
170 bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
170 bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
171 bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
171 bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
172 end
172 end
173 end
173 end
174 end
174 end
175
175
176 # horizontal input for radio buttons and check boxes
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 b.use :html5
178 b.use :html5
179 b.optional :readonly
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 b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
181 b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
182 ba.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
182 ba.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
183 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
183 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
184 ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
184 ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
185 end
185 end
186 end
186 end
187
187
188 # horizontal input for inline radio buttons and check boxes
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 b.use :html5
190 b.use :html5
191 b.optional :readonly
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 b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
193 b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
194 ba.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
194 ba.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
195 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
195 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
196 ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
196 ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
197 end
197 end
198 end
198 end
199
199
200 # horizontal file input
200 # 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|
201 config.wrappers :horizontal_file, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
202 b.use :html5
202 b.use :html5
203 b.use :placeholder
203 b.use :placeholder
204 b.optional :maxlength
204 b.optional :maxlength
205 b.optional :minlength
205 b.optional :minlength
206 b.optional :readonly
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 b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
208 b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
209 ba.use :input, error_class: 'is-invalid', valid_class: 'is-valid'
209 ba.use :input, error_class: 'is-invalid', valid_class: 'is-valid'
210 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
210 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
211 ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
211 ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
212 end
212 end
213 end
213 end
214
214
215 # horizontal multi select
215 # 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|
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 b.use :html5
217 b.use :html5
218 b.optional :readonly
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 b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
220 b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
221 ba.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |bb|
221 ba.wrapper tag: 'div', 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'
222 bb.use :input, class: 'form-control mx-1', error_class: 'is-invalid', valid_class: 'is-valid'
223 end
223 end
224 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
224 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
225 ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
225 ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
226 end
226 end
227 end
227 end
228
228
229 # horizontal range input
229 # 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|
230 config.wrappers :horizontal_range, tag: 'div', class: 'form-group row', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
231 b.use :html5
231 b.use :html5
232 b.use :placeholder
232 b.use :placeholder
233 b.optional :readonly
233 b.optional :readonly
234 b.optional :step
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 b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
236 b.wrapper :grid_wrapper, tag: 'div', class: 'col-sm-9' do |ba|
237 ba.use :input, class: 'form-control-range', error_class: 'is-invalid', valid_class: 'is-valid'
237 ba.use :input, class: 'form-control-range', error_class: 'is-invalid', valid_class: 'is-valid'
238 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
238 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
239 ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
239 ba.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
240 end
240 end
241 end
241 end
242
242
243
243
244 # inline forms
244 # inline forms
245 #
245 #
246 # inline default_wrapper
246 # inline default_wrapper
247 config.wrappers :inline_form, tag: 'span', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
247 config.wrappers :inline_form, tag: 'span', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
248 b.use :html5
248 b.use :html5
249 b.use :placeholder
249 b.use :placeholder
250 b.optional :maxlength
250 b.optional :maxlength
251 b.optional :minlength
251 b.optional :minlength
252 b.optional :pattern
252 b.optional :pattern
253 b.optional :min_max
253 b.optional :min_max
254 b.optional :readonly
254 b.optional :readonly
255 b.use :label, class: 'sr-only'
255 b.use :label, class: 'sr-only'
256
256
257 b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
257 b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
258 b.use :error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
258 b.use :error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
259 b.optional :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
259 b.optional :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
260 end
260 end
261
261
262 # inline input for boolean
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 b.use :html5
264 b.use :html5
265 b.optional :readonly
265 b.optional :readonly
266 b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
266 b.use :input, class: 'form-check-input', error_class: 'is-invalid', valid_class: 'is-valid'
267 b.use :label, class: 'form-check-label'
267 b.use :label, class: 'form-check-label'
268 b.use :error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
268 b.use :error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
269 b.optional :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
269 b.optional :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
270 end
270 end
271
271
272
272
273 # bootstrap custom forms
273 # bootstrap custom forms
274 #
274 #
275 # custom input for boolean
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|
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
277 b.use :html5
278 b.optional :readonly
278 b.optional :readonly
279 b.wrapper :form_check_wrapper, tag: 'div', class: 'custom-control custom-checkbox' do |bb|
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'
280 bb.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
281 bb.use :label, class: 'custom-control-label'
281 bb.use :label, class: 'custom-control-label'
282 bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
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' }
283 bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
284 end
284 end
285 end
285 end
286
286
287 + # custom input switch for boolean
287 config.wrappers :custom_boolean_switch, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
288 config.wrappers :custom_boolean_switch, tag: 'fieldset', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
288 b.use :html5
289 b.use :html5
289 b.optional :readonly
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 bb.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
292 bb.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
292 bb.use :label, class: 'custom-control-label'
293 bb.use :label, class: 'custom-control-label'
293 bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
294 bb.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
294 bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
295 bb.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
295 end
296 end
296 end
297 end
297
298
298 # custom input for radio buttons and check boxes
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 b.use :html5
301 b.use :html5
301 b.optional :readonly
302 b.optional :readonly
302 b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
303 b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
303 ba.use :label_text
304 ba.use :label_text
304 end
305 end
305 b.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
306 b.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
306 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
307 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
307 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
308 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
308 end
309 end
309
310
310 # custom input for inline radio buttons and check boxes
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 b.use :html5
313 b.use :html5
313 b.optional :readonly
314 b.optional :readonly
314 b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
315 b.wrapper :legend_tag, tag: 'legend', class: 'col-form-label pt-0' do |ba|
315 ba.use :label_text
316 ba.use :label_text
316 end
317 end
317 b.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
318 b.use :input, class: 'custom-control-input', error_class: 'is-invalid', valid_class: 'is-valid'
318 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
319 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
319 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
320 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
320 end
321 end
321
322
322 # custom file input
323 # custom file input
323 config.wrappers :custom_file, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
324 config.wrappers :custom_file, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
324 b.use :html5
325 b.use :html5
325 b.use :placeholder
326 b.use :placeholder
326 b.optional :maxlength
327 b.optional :maxlength
327 b.optional :minlength
328 b.optional :minlength
328 b.optional :readonly
329 b.optional :readonly
329 - b.use :label, class: 'form-control-label'
330 + b.use :label
330 b.wrapper :custom_file_wrapper, tag: 'div', class: 'custom-file' do |ba|
331 b.wrapper :custom_file_wrapper, tag: 'div', class: 'custom-file' do |ba|
331 ba.use :input, class: 'custom-file-input', error_class: 'is-invalid', valid_class: 'is-valid'
332 ba.use :input, class: 'custom-file-input', error_class: 'is-invalid', valid_class: 'is-valid'
332 ba.use :label, class: 'custom-file-label'
333 ba.use :label, class: 'custom-file-label'
333 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
334 ba.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
334 end
335 end
335 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
336 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
336 end
337 end
337
338
338 # custom multi select
339 # custom multi select
339 config.wrappers :custom_multi_select, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
340 config.wrappers :custom_multi_select, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
340 b.use :html5
341 b.use :html5
341 b.optional :readonly
342 b.optional :readonly
342 - b.use :label, class: 'form-control-label'
343 + b.use :label
343 b.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |ba|
344 b.wrapper tag: 'div', class: 'd-flex flex-row justify-content-between align-items-center' do |ba|
344 ba.use :input, class: 'custom-select mx-1', error_class: 'is-invalid', valid_class: 'is-valid'
345 ba.use :input, class: 'custom-select mx-1', error_class: 'is-invalid', valid_class: 'is-valid'
345 end
346 end
346 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
347 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
347 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
348 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
348 end
349 end
349
350
350 # custom range input
351 # custom range input
351 config.wrappers :custom_range, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
352 config.wrappers :custom_range, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
352 b.use :html5
353 b.use :html5
353 b.use :placeholder
354 b.use :placeholder
354 b.optional :readonly
355 b.optional :readonly
355 b.optional :step
356 b.optional :step
356 - b.use :label, class: 'form-control-label'
357 + b.use :label
357 b.use :input, class: 'custom-range', error_class: 'is-invalid', valid_class: 'is-valid'
358 b.use :input, class: 'custom-range', error_class: 'is-invalid', valid_class: 'is-valid'
358 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
359 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
359 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
360 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
360 end
361 end
361
362
362
363
363 # Input Group - custom component
364 # Input Group - custom component
364 # see example app and config at https://github.com/rafaelfranca/simple_form-bootstrap
365 # see example app and config at https://github.com/rafaelfranca/simple_form-bootstrap
365 # config.wrappers :input_group, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
366 # config.wrappers :input_group, tag: 'div', class: 'form-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
366 # b.use :html5
367 # b.use :html5
367 # b.use :placeholder
368 # b.use :placeholder
368 # b.optional :maxlength
369 # b.optional :maxlength
369 # b.optional :minlength
370 # b.optional :minlength
370 # b.optional :pattern
371 # b.optional :pattern
371 # b.optional :min_max
372 # b.optional :min_max
372 # b.optional :readonly
373 # b.optional :readonly
373 - # b.use :label, class: 'form-control-label'
374 + # b.use :label
374 # b.wrapper :input_group_tag, tag: 'div', class: 'input-group' do |ba|
375 # b.wrapper :input_group_tag, tag: 'div', class: 'input-group' do |ba|
375 # ba.optional :prepend
376 # ba.optional :prepend
376 # ba.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
377 # ba.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
377 # ba.optional :append
378 # ba.optional :append
378 # end
379 # end
379 # b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
380 # b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback d-block' }
380 # b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
381 # b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
381 # end
382 # end
382
383
383
384
384 # Floating Labels form
385 # Floating Labels form
385 #
386 #
386 # floating labels default_wrapper
387 # floating labels default_wrapper
387 config.wrappers :floating_labels_form, tag: 'div', class: 'form-label-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
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 b.use :html5
389 b.use :html5
389 b.use :placeholder
390 b.use :placeholder
390 b.optional :maxlength
391 b.optional :maxlength
391 b.optional :minlength
392 b.optional :minlength
392 b.optional :pattern
393 b.optional :pattern
393 b.optional :min_max
394 b.optional :min_max
394 b.optional :readonly
395 b.optional :readonly
395 b.use :input, class: 'form-control', error_class: 'is-invalid', valid_class: 'is-valid'
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 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
398 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
398 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
399 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
399 end
400 end
400
401
401 # custom multi select
402 # custom multi select
402 config.wrappers :floating_labels_select, tag: 'div', class: 'form-label-group', error_class: 'form-group-invalid', valid_class: 'form-group-valid' do |b|
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 b.use :html5
404 b.use :html5
404 b.optional :readonly
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 :input, class: 'custom-select', error_class: 'is-invalid', valid_class: 'is-valid'
406 - b.use :label, class: 'form-control-label'
407 + b.use :label
407 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
408 b.use :full_error, wrap_with: { tag: 'div', class: 'invalid-feedback' }
408 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
409 b.use :hint, wrap_with: { tag: 'small', class: 'form-text text-muted' }
409 end
410 end
410
411
411
412
412 # The default wrapper to be used by the FormBuilder.
413 # The default wrapper to be used by the FormBuilder.
413 config.default_wrapper = :vertical_form
414 config.default_wrapper = :vertical_form
414
415
415 # Custom wrappers for input types. This should be a hash containing an input
416 # Custom wrappers for input types. This should be a hash containing an input
416 # type as key and the wrapper that will be used for all inputs with specified type.
417 # type as key and the wrapper that will be used for all inputs with specified type.
417 config.wrapper_mappings = {
418 config.wrapper_mappings = {
418 boolean: :vertical_boolean,
419 boolean: :vertical_boolean,
419 check_boxes: :vertical_collection,
420 check_boxes: :vertical_collection,
420 date: :vertical_multi_select,
421 date: :vertical_multi_select,
421 datetime: :vertical_multi_select,
422 datetime: :vertical_multi_select,
422 file: :vertical_file,
423 file: :vertical_file,
423 radio_buttons: :vertical_collection,
424 radio_buttons: :vertical_collection,
424 range: :vertical_range,
425 range: :vertical_range,
425 time: :vertical_multi_select
426 time: :vertical_multi_select
426 }
427 }
427
428
428 # enable custom form wrappers
429 # enable custom form wrappers
429 # config.wrapper_mappings = {
430 # config.wrapper_mappings = {
430 # boolean: :custom_boolean,
431 # boolean: :custom_boolean,
You need to be logged in to leave comments. Login now