simple_form_bs5_file_input 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1d471d34041e586ad2c8c3ef309ccb56730677ed198daf08e5a14e014b1f66e2
4
+ data.tar.gz: 45d007078895c2229164228d776be1dd0e2d6182b2140e34d1f91491ce8d1aa7
5
+ SHA512:
6
+ metadata.gz: 8a232a086495c5b63b5228cb01abbffb6e6edccb3234f39a5cd1e816ef4cea5d747a2b145516d3e7562f10d67436991077757cfbde56a41e97f9c646ea8f6e05
7
+ data.tar.gz: b89e928a07c3b264543779b5a798a3b11bbae7d0f9074ce8a1312d74b347023bac1c339198d11e790b1bc1a96a8244b79540a81943aeb2723aa3cc49ae7c158b
data/.eslintrc.yml ADDED
@@ -0,0 +1,180 @@
1
+ env:
2
+ browser: true
3
+ extends: "eslint:recommended"
4
+ rules:
5
+ # key: 0 = allow, 1 = warn, 2 = error
6
+
7
+ # Possible Errors
8
+ no-await-in-loop: 1
9
+ no-console: 1
10
+ no-extra-parens: [1, 'all']
11
+ no-template-curly-in-string: 0
12
+
13
+ # Best Practices
14
+ accessor-pairs: 0
15
+ array-callback-return: 0
16
+ block-scoped-var: 1
17
+ class-methods-use-this: 0
18
+ complexity: 0
19
+ consistent-return: 0
20
+ curly: [1, 'all']
21
+ default-case: 1
22
+ dot-location: [1, 'property']
23
+ dot-notation: 0
24
+ eqeqeq: 1
25
+ guard-for-in: 0
26
+ max-classes-per-file: 0
27
+ no-alert: 1
28
+ no-caller: 1
29
+ no-div-regex: 1
30
+ no-else-return: 0
31
+ no-empty-function: 1
32
+ no-eq-null: 1
33
+ no-eval: 0
34
+ no-extend-native: 0
35
+ no-extra-bind: 0
36
+ no-extra-label: 1
37
+ no-floating-decimal: 1
38
+ no-implicit-coercion: 1
39
+ no-implied-eval: 1
40
+ no-invalid-this: 0
41
+ no-iterator: 1
42
+ no-labels: 0
43
+ no-lone-blocks: 1
44
+ no-loop-func: 1
45
+ no-magic-numbers: 0
46
+ no-multi-spaces: 1
47
+ no-multi-str: 1
48
+ no-new: 0
49
+ no-new-func: 1
50
+ no-new-wrappers: 1
51
+ no-octal-escape: 1
52
+ no-param-reassign: 1
53
+ no-proto: 1
54
+ no-restricted-globals: 1
55
+ no-restricted-properties: 0
56
+ no-return-assign: 1
57
+ no-return-await: 1
58
+ no-script-url: 1
59
+ no-self-compare: 1
60
+ no-sequences: 1
61
+ no-throw-literal: 1
62
+ no-unmodified-loop-condition: 1
63
+ no-unused-expressions: 1
64
+ no-useless-call: 1
65
+ no-useless-concat: 1
66
+ no-useless-return: 1
67
+ no-void: 1
68
+ no-warning-comments: 0
69
+ prefer-named-capture-group: 0
70
+ prefer-promise-reject-errors: 1
71
+ radix: 1
72
+ require-await: 1
73
+ require-unicode-regexp: 0
74
+ vars-on-top: 1
75
+ wrap-iife: 1
76
+ yoda: 1
77
+
78
+ # Strict Mode
79
+ strict: [1, 'safe']
80
+
81
+ # Variables
82
+ init-declarations: 0
83
+ no-label-var: 1
84
+ no-implicit-globals: 0
85
+ no-shadow: 1
86
+ no-undef-init: 1
87
+ no-undefined: 1
88
+ no-use-before-define: 1
89
+
90
+ # Stylistic Issues
91
+ array-bracket-newline: 0
92
+ array-bracket-spacing: [1, 'never']
93
+ array-element-newline: 0
94
+ block-spacing: [1, 'always']
95
+ brace-style: [1, '1tbs']
96
+ camelcase: 1
97
+ capitalized-comments: 0
98
+ comma-dangle: [1, 'never']
99
+ comma-spacing: [1, { "before": false, "after": true }]
100
+ comma-style: 1
101
+ computed-property-spacing: [1, 'never']
102
+ consistent-this: [1, 'that']
103
+ eol-last: 1
104
+ func-call-spacing: [1, 'never']
105
+ func-name-matching: [1, 'always']
106
+ func-names: 0
107
+ func-style: [1, 'expression']
108
+ function-paren-newline: [1, 'never']
109
+ id-blacklist: 0
110
+ id-length: 0
111
+ id-match: 0
112
+ implicit-arrow-linebreak: 0
113
+ indent: [1, 4]
114
+ jsx-quotes: 0
115
+ key-spacing: 1
116
+ keyword-spacing: 1
117
+ line-comment-position: [1, 'above']
118
+ linebreak-style: [1, 'unix']
119
+ lines-around-comment: 0
120
+ lines-between-class-members: [1, 'always', { exceptAfterSingleLine: true }]
121
+ max-depth: [1, 4]
122
+ max-len: 0
123
+ max-lines: 0
124
+ max-lines-per-function: 0
125
+ max-nested-callbacks: 0
126
+ max-params: [1, 4]
127
+ max-statements: 0
128
+ max-statements-per-line: [1, { max: 1 }]
129
+ multiline-comment-style: 0
130
+ multiline-ternary: 0
131
+ new-cap: 1
132
+ new-parens: 1
133
+ newline-per-chained-call: 1
134
+ no-array-constructor: 0
135
+ no-bitwise: 0
136
+ no-continue: 0
137
+ no-inline-comments: 0
138
+ no-lonely-if: 1
139
+ no-mixed-operators: 0
140
+ no-multi-assign: 1
141
+ no-multiple-empty-lines: 1
142
+ no-negated-condition: 0
143
+ no-nested-ternary: 1
144
+ no-new-object: 0
145
+ no-plusplus: 1
146
+ no-restricted-syntax: 0
147
+ no-tabs: 1
148
+ no-ternary: 0
149
+ no-trailing-spaces: 1
150
+ no-underscore-dangle: 1
151
+ no-unneeded-ternary: 1
152
+ no-whitespace-before-property: 1
153
+ nonblock-statement-body-position: 1
154
+ object-curly-newline: 0
155
+ object-curly-spacing: [1, 'always']
156
+ object-property-newline: 0
157
+ one-var: [1, 'consecutive']
158
+ one-var-declaration-per-line: [1, 'always']
159
+ operator-assignment: [1, 'always']
160
+ operator-linebreak: 0
161
+ padded-blocks: [1, 'never']
162
+ padding-line-between-statements: 0
163
+ prefer-object-spread: 0
164
+ quote-props: 0
165
+ quotes: [1, 'single']
166
+ semi: [1, 'always']
167
+ semi-spacing: [1, { before: false, after: true }]
168
+ semi-style: [1, 'last']
169
+ sort-keys: 0
170
+ sort-vars: 0
171
+ space-before-blocks: [1, 'always']
172
+ space-before-function-paren: [1, 'always']
173
+ space-in-parens: [1, 'never']
174
+ space-infix-ops: 0
175
+ space-unary-ops: [1, { words: true, nonwords: false }]
176
+ spaced-comment: [1, 'always', { markers: ["global", "="] }]
177
+ switch-colon-spacing: [1, { after: true, before: false }]
178
+ template-tag-spacing: [1, 'always']
179
+ unicode-bom: [1, 'never']
180
+ wrap-regex: 1
data/.sass-lint.yml ADDED
@@ -0,0 +1,55 @@
1
+ # Linter Options
2
+ options:
3
+ # Don't merge default rules
4
+ merge-default-rules: false
5
+ # Set the formatter to 'html'
6
+ formatter: html
7
+ # Output file instead of logging results
8
+ output-file: 'linters/sass-lint.html'
9
+ # Raise an error if more than 50 warnings are generated
10
+ max-warnings: 50
11
+ # File Options
12
+ files:
13
+ include:
14
+ - 'app/assets/stylesheets/**/*.s+(a|c)ss'
15
+ - 'docs/themes/**/*.s+(a|c)ss'
16
+ ignore:
17
+ - 'vendor/**/*.*'
18
+ # Rule Configuration
19
+ rules:
20
+ class-name-format: 0
21
+ extends-before-mixins: 2
22
+ extends-before-declarations: 2
23
+ mixins-before-declarations:
24
+ - 2
25
+ -
26
+ exclude:
27
+ - breakpoint
28
+ - breakpoint-next
29
+ - breakpoint-min
30
+ - breakpoint-max
31
+ - breakpoint-infix
32
+ - media-breakpoint-up
33
+ - media-breakpoint-down
34
+ - media-breakpoint-between
35
+ - media-breakpoint-only
36
+ - mq
37
+ no-warn: 1
38
+ no-debug: 1
39
+ hex-length:
40
+ - 2
41
+ -
42
+ style: long
43
+ hex-notation:
44
+ - 2
45
+ -
46
+ style: uppercase
47
+ indentation:
48
+ - 4
49
+ -
50
+ size: 4
51
+ property-sort-order:
52
+ - 1
53
+ -
54
+ order: alphabetical
55
+ ignore-custom-properties: false
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ gem 'simple_form'
6
+
7
+ # Specify your gem's dependencies in simple_form_bs5_file_input.gemspec
8
+ gemspec
9
+
10
+ gem 'pg', '~> 1.1'
11
+ gem 'bootsnap', '>= 1.4.4', require: false
12
+ gem 'devise'
13
+ gem 'bootstrap'
14
+ gem 'jquery-rails'
data/Gemfile.lock ADDED
@@ -0,0 +1,202 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ simple_form_bs5_file_input (0.0.1)
5
+ rails
6
+ simple_form
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ actioncable (6.1.4.1)
12
+ actionpack (= 6.1.4.1)
13
+ activesupport (= 6.1.4.1)
14
+ nio4r (~> 2.0)
15
+ websocket-driver (>= 0.6.1)
16
+ actionmailbox (6.1.4.1)
17
+ actionpack (= 6.1.4.1)
18
+ activejob (= 6.1.4.1)
19
+ activerecord (= 6.1.4.1)
20
+ activestorage (= 6.1.4.1)
21
+ activesupport (= 6.1.4.1)
22
+ mail (>= 2.7.1)
23
+ actionmailer (6.1.4.1)
24
+ actionpack (= 6.1.4.1)
25
+ actionview (= 6.1.4.1)
26
+ activejob (= 6.1.4.1)
27
+ activesupport (= 6.1.4.1)
28
+ mail (~> 2.5, >= 2.5.4)
29
+ rails-dom-testing (~> 2.0)
30
+ actionpack (6.1.4.1)
31
+ actionview (= 6.1.4.1)
32
+ activesupport (= 6.1.4.1)
33
+ rack (~> 2.0, >= 2.0.9)
34
+ rack-test (>= 0.6.3)
35
+ rails-dom-testing (~> 2.0)
36
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
37
+ actiontext (6.1.4.1)
38
+ actionpack (= 6.1.4.1)
39
+ activerecord (= 6.1.4.1)
40
+ activestorage (= 6.1.4.1)
41
+ activesupport (= 6.1.4.1)
42
+ nokogiri (>= 1.8.5)
43
+ actionview (6.1.4.1)
44
+ activesupport (= 6.1.4.1)
45
+ builder (~> 3.1)
46
+ erubi (~> 1.4)
47
+ rails-dom-testing (~> 2.0)
48
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
49
+ activejob (6.1.4.1)
50
+ activesupport (= 6.1.4.1)
51
+ globalid (>= 0.3.6)
52
+ activemodel (6.1.4.1)
53
+ activesupport (= 6.1.4.1)
54
+ activerecord (6.1.4.1)
55
+ activemodel (= 6.1.4.1)
56
+ activesupport (= 6.1.4.1)
57
+ activestorage (6.1.4.1)
58
+ actionpack (= 6.1.4.1)
59
+ activejob (= 6.1.4.1)
60
+ activerecord (= 6.1.4.1)
61
+ activesupport (= 6.1.4.1)
62
+ marcel (~> 1.0.0)
63
+ mini_mime (>= 1.1.0)
64
+ activesupport (6.1.4.1)
65
+ concurrent-ruby (~> 1.0, >= 1.0.2)
66
+ i18n (>= 1.6, < 2)
67
+ minitest (>= 5.1)
68
+ tzinfo (~> 2.0)
69
+ zeitwerk (~> 2.3)
70
+ autoprefixer-rails (10.3.3.0)
71
+ execjs (~> 2)
72
+ bcrypt (3.1.16)
73
+ bootsnap (1.9.1)
74
+ msgpack (~> 1.0)
75
+ bootstrap (5.1.0)
76
+ autoprefixer-rails (>= 9.1.0)
77
+ popper_js (>= 2.9.3, < 3)
78
+ sassc-rails (>= 2.0.0)
79
+ builder (3.2.4)
80
+ concurrent-ruby (1.1.9)
81
+ crass (1.0.6)
82
+ devise (4.8.0)
83
+ bcrypt (~> 3.0)
84
+ orm_adapter (~> 0.1)
85
+ railties (>= 4.1.0)
86
+ responders
87
+ warden (~> 1.2.3)
88
+ erubi (1.10.0)
89
+ execjs (2.8.1)
90
+ ffi (1.15.4)
91
+ globalid (0.5.2)
92
+ activesupport (>= 5.0)
93
+ i18n (1.8.10)
94
+ concurrent-ruby (~> 1.0)
95
+ jquery-rails (4.4.0)
96
+ rails-dom-testing (>= 1, < 3)
97
+ railties (>= 4.2.0)
98
+ thor (>= 0.14, < 2.0)
99
+ listen (3.7.0)
100
+ rb-fsevent (~> 0.10, >= 0.10.3)
101
+ rb-inotify (~> 0.9, >= 0.9.10)
102
+ loofah (2.12.0)
103
+ crass (~> 1.0.2)
104
+ nokogiri (>= 1.5.9)
105
+ mail (2.7.1)
106
+ mini_mime (>= 0.1.1)
107
+ marcel (1.0.2)
108
+ method_source (1.0.0)
109
+ mini_mime (1.1.2)
110
+ mini_portile2 (2.6.1)
111
+ minitest (5.14.4)
112
+ msgpack (1.4.2)
113
+ nio4r (2.5.8)
114
+ nokogiri (1.12.5)
115
+ mini_portile2 (~> 2.6.1)
116
+ racc (~> 1.4)
117
+ orm_adapter (0.5.0)
118
+ pg (1.2.3)
119
+ popper_js (2.9.3)
120
+ racc (1.5.2)
121
+ rack (2.2.3)
122
+ rack-test (1.1.0)
123
+ rack (>= 1.0, < 3)
124
+ rails (6.1.4.1)
125
+ actioncable (= 6.1.4.1)
126
+ actionmailbox (= 6.1.4.1)
127
+ actionmailer (= 6.1.4.1)
128
+ actionpack (= 6.1.4.1)
129
+ actiontext (= 6.1.4.1)
130
+ actionview (= 6.1.4.1)
131
+ activejob (= 6.1.4.1)
132
+ activemodel (= 6.1.4.1)
133
+ activerecord (= 6.1.4.1)
134
+ activestorage (= 6.1.4.1)
135
+ activesupport (= 6.1.4.1)
136
+ bundler (>= 1.15.0)
137
+ railties (= 6.1.4.1)
138
+ sprockets-rails (>= 2.0.0)
139
+ rails-dom-testing (2.0.3)
140
+ activesupport (>= 4.2.0)
141
+ nokogiri (>= 1.6)
142
+ rails-html-sanitizer (1.4.2)
143
+ loofah (~> 2.3)
144
+ railties (6.1.4.1)
145
+ actionpack (= 6.1.4.1)
146
+ activesupport (= 6.1.4.1)
147
+ method_source
148
+ rake (>= 0.13)
149
+ thor (~> 1.0)
150
+ rake (13.0.6)
151
+ rb-fsevent (0.11.0)
152
+ rb-inotify (0.10.1)
153
+ ffi (~> 1.0)
154
+ responders (3.0.1)
155
+ actionpack (>= 5.0)
156
+ railties (>= 5.0)
157
+ sassc (2.4.0)
158
+ ffi (~> 1.9)
159
+ sassc-rails (2.1.2)
160
+ railties (>= 4.0.0)
161
+ sassc (>= 2.0)
162
+ sprockets (> 3.0)
163
+ sprockets-rails
164
+ tilt
165
+ simple_form (5.1.0)
166
+ actionpack (>= 5.2)
167
+ activemodel (>= 5.2)
168
+ sprockets (4.0.2)
169
+ concurrent-ruby (~> 1.0)
170
+ rack (> 1, < 3)
171
+ sprockets-rails (3.2.2)
172
+ actionpack (>= 4.0)
173
+ activesupport (>= 4.0)
174
+ sprockets (>= 3.0.0)
175
+ sqlite3 (1.4.2)
176
+ thor (1.1.0)
177
+ tilt (2.0.10)
178
+ tzinfo (2.0.4)
179
+ concurrent-ruby (~> 1.0)
180
+ warden (1.2.9)
181
+ rack (>= 2.0.9)
182
+ websocket-driver (0.7.5)
183
+ websocket-extensions (>= 0.1.0)
184
+ websocket-extensions (0.1.5)
185
+ zeitwerk (2.4.2)
186
+
187
+ PLATFORMS
188
+ ruby
189
+
190
+ DEPENDENCIES
191
+ bootsnap (>= 1.4.4)
192
+ bootstrap
193
+ devise
194
+ jquery-rails
195
+ listen
196
+ pg (~> 1.1)
197
+ simple_form
198
+ simple_form_bs5_file_input!
199
+ sqlite3
200
+
201
+ BUNDLED WITH
202
+ 2.1.4
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Noesya
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # simple_form_bs5_file_input
2
+
3
+ A nice improvement for the `file` field in [Simple Form](https://github.com/heartcombo/simple_form).
4
+
5
+ **Simple Form Bootstrap 5 File Input** aims to add directs controls to your file fields in Simple Form.
6
+
7
+
8
+ ## Installation
9
+
10
+ Add it to your Gemfile:
11
+
12
+ ```ruby
13
+ gem 'simple_form_bs5_file_input'
14
+ ```
15
+
16
+ Run the following command to install it:
17
+
18
+ ```console
19
+ bundle install
20
+ ```
21
+
22
+ Add it to your application.sass:
23
+
24
+ ```
25
+ @import 'simple_form_bs5_file_input'
26
+ ```
27
+
28
+ Add it to your application.js:
29
+
30
+ ```
31
+ //= require simple_form_bs5_file_input
32
+ ```
33
+
34
+ ### Active Storage
35
+
36
+ **Simple Form Bootstrap 5 File Input** relies on [Active Storage](https://github.com/rails/rails/tree/main/activestorage), so it presumes that you installed Active Storage.
37
+
38
+ ### Bootstrap
39
+
40
+ **Simple Form Bootstrap 5 File Input** relies on the [Bootstrap 5](http://getbootstrap.com/) markup, so it presumes that you installed Simple Form with the Bootstrap option. To do that you have to use the `bootstrap` option in the Simple Form install generator, like this:
41
+
42
+ ```console
43
+ rails generate simple_form:install --bootstrap
44
+ ```
45
+
46
+ You have to be sure that you added a copy of the [Bootstrap 5](http://getbootstrap.com/)
47
+ assets on your application.
48
+
49
+ ## Usage
50
+ **Simple Form Bootstrap 5 File Input** comes with one new input type which is meant to replace the standard `:file` field: `:single_deletable_file`
51
+
52
+ To start using **Simple Form Bootstrap 5 File Input** you just have to change the input type of the `:file` field to these new kind.
53
+
54
+ So basically your field:
55
+ ```erb
56
+ <%= f.input :my_file %>
57
+ ```
58
+ becomes
59
+ ```erb
60
+ <%= f.input :my_file,
61
+ as: :single_deletable_file %>
62
+ ```
63
+ Of course you can still add the options you want, like for example `input_html: { accept: '.jpg,.jpeg,.png' }`
64
+
65
+ You can also add a direct preview (WARNING: preview can only work with images!) by using `preview: true` or any custom width for the preview: `preview: 500`. If you don't specify the preview size it will be 1000px witdh by default.
66
+ Note that the preview uses the boostrap classes `img-fluid` and `img-thumbnail`.
67
+
68
+
69
+ ### Direct upload
70
+
71
+ The new field is still compatible with the `direct_upload` param.
72
+ ```erb
73
+ <%= f.input :my_file,
74
+ as: :single_deletable_file,
75
+ direct_upload: true %>
76
+ ```
77
+ Please remember to include the `activestorage.js` library in order to use the direct_upload feature.
78
+ Direct upload will send the file BEFORE the page submission. You will get a progress bar in the file field while the file is uploading.
79
+
80
+
81
+ ## I18n
82
+
83
+ **Simple Form Bootstrap 5 File Input** uses the I18n API to manage the texts displayed. Feel free to overwrite the keys or add languages.
84
+
85
+ ## Information
86
+
87
+ ### Supported Ruby / Rails versions
88
+
89
+ We intend to maintain support for all Ruby / Rails versions that haven't reached end-of-life.
90
+
91
+ For more information about specific versions please check [Ruby](https://www.ruby-lang.org/en/downloads/branches/)
92
+ and [Rails](https://guides.rubyonrails.org/maintenance_policy.html) maintenance policies, and our test matrix.
93
+
94
+ ### Bug reports
95
+
96
+ If you discover any bugs, feel free to create an issue on GitHub. Please add as much information as
97
+ possible to help us in fixing the potential bug. We also encourage you to help even more by forking and sending us a pull request.
98
+
99
+ https://github.com/noesya/simple_form_bs5_file_input/issues
100
+
101
+ ## Maintainers
102
+
103
+ * Pierre-André Boissinot (https://github.com/pabois)
104
+
105
+
106
+ ## License
107
+
108
+ MIT License.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512.001 512.001"><path fill="#E40000" d="M294.111 256.001L504.109 46.003c10.523-10.524 10.523-27.586 0-38.109-10.524-10.524-27.587-10.524-38.11 0L256 217.892 46.002 7.894C35.478-2.63 18.416-2.63 7.893 7.894s-10.524 27.586 0 38.109l209.998 209.998L7.893 465.999c-10.524 10.524-10.524 27.586 0 38.109 10.524 10.524 27.586 10.523 38.109 0L256 294.11l209.997 209.998c10.524 10.524 27.587 10.523 38.11 0 10.523-10.524 10.523-27.586 0-38.109L294.111 256.001z"/></svg>
@@ -0,0 +1,85 @@
1
+ /*global $, document, window */
2
+ window.inputSingleDeletableFile = {
3
+ onDelete: function (e) {
4
+ 'use strict';
5
+ var $scope = $(this).parents('.js-sdfi-deletable-file');
6
+ e.preventDefault();
7
+ e.stopPropagation();
8
+ $('.js-sdfi-deletable-file__hidden-field', $scope).val('true');
9
+ $('input[type="file"]', $scope).val('');
10
+ $scope.removeClass('sdfi-deletable-file--with-file');
11
+ // $('.custom-file-preview', scope).hide();
12
+ },
13
+
14
+ onChange: function () {
15
+ 'use strict';
16
+ var $scope = $(this).parents('.js-sdfi-deletable-file'),
17
+ fileName = $(this).val()
18
+ .split('\\')
19
+ .pop(),
20
+ hasPreview = $('.js-sdfi-deletable-file__preview', $scope).length > 0,
21
+ reader,
22
+ size;
23
+ if (fileName !== '') {
24
+ $scope.addClass('sdfi-deletable-file--with-file');
25
+ $('.js-sdfi-deletable-file__label', $scope).html(fileName);
26
+ $('.js-sdfi-deletable-file__hidden-field', $scope).val('');
27
+ }
28
+ // preview
29
+ if (hasPreview && this.files && this.files[0]) {
30
+ size = $('.js-sdfi-deletable-file__preview', $scope).attr('data-size')
31
+ .split('x');
32
+ reader = new FileReader();
33
+ reader.onload = function (e) {
34
+ $('.js-sdfi-deletable-file__preview', $scope).html('<img src="' + e.target.result + '" width="' + size[0] + '" height="auto" class="img-fluid img-thumbnail">');
35
+ };
36
+ reader.readAsDataURL(this.files[0]);
37
+ }
38
+ },
39
+
40
+ bindEvents: function (field) {
41
+ 'use strict';
42
+ // click on the fake "replace file" btn launch the file input choice
43
+ $('.js-sdfi-deletable-file__change-btn', $(field)).on('click', function () {
44
+ $('input[type="file"]', $(field)).click();
45
+ });
46
+ $('.js-sdfi-deletable-file__delete-btn', $(field)).on('click', this.onDelete);
47
+ $('input[type="file"]', $(field)).on('change', this.onChange);
48
+ }
49
+ };
50
+
51
+ $(document).ready(function () {
52
+ 'use strict';
53
+ $('.js-sdfi-deletable-file').each(function () {
54
+ window.inputSingleDeletableFile.bindEvents(this);
55
+ });
56
+ });
57
+
58
+ /* Direct upload methods */
59
+
60
+ window.addEventListener('direct-upload:initialize', function (event) {
61
+ 'use strict';
62
+ var target = event.target,
63
+ $scope = $(target).parents('.js-sdfi-deletable-file');
64
+ $('.sdfi-deletable-file__upload-progress', $scope).css('width', '0%');
65
+ $scope.addClass('sdfi-deletable-file--uploading');
66
+ });
67
+
68
+ window.addEventListener('direct-upload:progress', function (event) {
69
+ 'use strict';
70
+ var target = event.target,
71
+ progress = event.detail.progress,
72
+ $scope = $(target).parents('.js-sdfi-deletable-file');
73
+ $('.sdfi-deletable-file__upload-progress', $scope).css('width', progress + '%');
74
+ });
75
+
76
+ window.addEventListener('direct-upload:error', function (event) {
77
+ 'use strict';
78
+ var target = event.target,
79
+ error = event.detail.error,
80
+ $scope = $(target).parents('.js-sdfi-deletable-file');
81
+ event.preventDefault();
82
+ $('.sdfi-deletable-file__upload-progress', $scope).css('width', '0%');
83
+ $scope.removeClass('sdfi-deletable-file--uploading');
84
+ alert(error);
85
+ });
@@ -0,0 +1,82 @@
1
+ .sdfi-deletable-file
2
+ position: relative
3
+
4
+ &__preview
5
+ margin-top: 1rem
6
+ display: none
7
+
8
+ &__block
9
+ display: none
10
+ padding: 0
11
+ position: relative
12
+
13
+ .btn
14
+ @include gradient-bg($form-file-button-bg)
15
+ border: 0
16
+ border-bottom-right-radius: 0
17
+ border-top-right-radius: 0
18
+ border-right: 1px solid var(--bs-gray-400)
19
+ color: $form-file-button-color
20
+ white-space: nowrap
21
+
22
+ &:focus
23
+ box-shadow: none
24
+
25
+ &:hover:not(:disabled):not([readonly])
26
+ background-color: $form-file-button-hover-bg
27
+
28
+ .sdfi-deletable-file__label
29
+ cursor: pointer
30
+ overflow: hidden
31
+ padding: .25rem .7rem
32
+ text-overflow: ellipsis
33
+ white-space: nowrap
34
+
35
+ &.is-valid
36
+ .btn
37
+ border-right-color: var(--bs-green)
38
+
39
+ &__delete-btn
40
+ align-self: center
41
+ background-color: white
42
+ background-image: asset-url('icon-cancel.svg')
43
+ background-position: center
44
+ background-repeat: no-repeat
45
+ background-size: .9em
46
+ cursor: pointer
47
+ flex-shrink: 0
48
+ height: 1.5rem
49
+ margin-right: .7rem
50
+ margin-top: 1px
51
+ width: calc(0.75em + 0.375rem)
52
+
53
+ &__upload-background, &__upload-progress
54
+ border-radius: .2rem
55
+ display: none
56
+ height: 100%
57
+ left: 0
58
+ position: absolute
59
+ top: 0
60
+
61
+ &__upload-background
62
+ background-color: #FFFFFF
63
+ width: 100%
64
+
65
+ &__upload-progress
66
+ background-color: #E0E0E0
67
+ pointer-events: none
68
+ width: 0%
69
+
70
+ &--with-file
71
+ input[type='file']
72
+ display: none
73
+
74
+ .sdfi-deletable-file__preview
75
+ display: flex
76
+
77
+ .sdfi-deletable-file__block
78
+ display: flex
79
+
80
+ &--uploading
81
+ .sdfi-deletable-file__upload-background, .sdfi-deletable-file__upload-progress
82
+ display: block
@@ -0,0 +1,3 @@
1
+ en:
2
+ simple_form_bs5_file_input:
3
+ replace_file: 'Change the file'
@@ -0,0 +1,3 @@
1
+ fr:
2
+ simple_form_bs5_file_input:
3
+ replace_file: 'Remplacer le fichier'
@@ -0,0 +1,53 @@
1
+ class ActiveRecord::Base
2
+ def self.has_one_attached_deletable(name, dependent: :purge_later)
3
+ class_eval do
4
+ attr_accessor :"#{name}_delete"
5
+ attr_accessor :"#{name}_infos"
6
+
7
+ before_validation { send(name).purge_later if send("#{name}_attachment").present? && send("#{name}_delete") == 'true' }
8
+ after_commit :"resize_#{name}", unless: Proc.new { |u| u.send("#{name}_infos").blank? }
9
+
10
+ define_method :"#{name}_delete=" do |value|
11
+ instance_variable_set :"@#{name}_delete", value
12
+ end
13
+
14
+ define_method :"resize_#{name}" do
15
+ return unless send(name).attached?
16
+
17
+ params = JSON(send("#{name}_infos"))
18
+ # reset the infos to prevent multiple resize if multiple save
19
+ instance_variable_set :"@#{name}_infos", nil
20
+
21
+ # From Rails 6, ImageProcessing uses an 'auto-orient' by default to interpret the EXIF Orientation metadata.
22
+ # We declare it in the transformations hash for Rails 5
23
+ transformations = {
24
+ :'auto-orient' => true,
25
+ crop: "#{params['width'].round}x#{params['height'].round}+#{params['x'].round}+#{params['y'].round}",
26
+ repage: true,
27
+ :'+' => true
28
+ }
29
+
30
+ variant = Rails::VERSION::MAJOR >= 6 ? send(name).variant(**transformations)
31
+ : send(name).variant(combine_options: transformations)
32
+
33
+ variant_url = variant.processed.service_url
34
+ downloaded_image = URI.open(variant_url)
35
+ attachable = { io: downloaded_image, filename: send(name).filename.to_s }
36
+
37
+ if Rails::VERSION::MAJOR >= 6
38
+ # Prevent double-update on the record, losing ActiveModel::Dirty data.
39
+ # Based on Rails source code:
40
+ # - https://github.com/rails/rails/blob/v6.0.2.2/activestorage/lib/active_storage/attached/model.rb
41
+ # - https://github.com/rails/rails/blob/v6.0.2.2/activestorage/lib/active_storage/attached/one.rb
42
+ attachment_change = ActiveStorage::Attached::Changes::CreateOne.new("#{name}", self, attachable)
43
+ attachment_change.save
44
+ attachment_change.upload
45
+ else
46
+ self.send(name).attach(**attachable)
47
+ end
48
+ end
49
+ end
50
+
51
+ has_one_attached name
52
+ end
53
+ end
@@ -0,0 +1,95 @@
1
+ class SingleDeletableFileInput < SimpleForm::Inputs::Base
2
+ delegate :url_helpers, to: 'Rails.application.routes'
3
+
4
+ include ActionView::Helpers::AssetTagHelper
5
+ include ActionDispatch::Routing::PolymorphicRoutes
6
+
7
+ def input(wrapper_options = nil)
8
+ format('
9
+ <div class="sdfi-deletable-file js-sdfi-deletable-file %s">
10
+ %s
11
+ <div class="%s">
12
+ <button type="button" class="btn js-sdfi-deletable-file__change-btn">%s</button>
13
+ <label for="%s" class="sdfi-deletable-file__label js-sdfi-deletable-file__label">
14
+ %s
15
+ </label>
16
+ <div class="sdfi-deletable-file__delete-btn js-sdfi-deletable-file__delete-btn"></div>
17
+ <div class="sdfi-deletable-file__upload-background"></div>
18
+ <div class="sdfi-deletable-file__upload-progress"></div>
19
+ <input type="hidden" name="%s" class="js-sdfi-deletable-file__hidden-field" %s />
20
+ </div>
21
+ %s
22
+ </div>
23
+ ', has_file_class, input_field(wrapper_options), field_classes(wrapper_options), change_file_text, field_id, existing_file_name_or_default_text, input_hidden_name, input_hidden_value, preview_div)
24
+ end
25
+
26
+ def preview_div
27
+ if options[:preview]
28
+ format('<div class="sdfi-deletable-file__preview js-sdfi-deletable-file__preview" data-size="%s">%s</div>', preview_image_width, preview_image_tag)
29
+ end
30
+ end
31
+
32
+ def has_file_class
33
+ 'sdfi-deletable-file--with-file' if should_display_file?
34
+ end
35
+
36
+ def input_field(wrapper_options)
37
+ merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
38
+ if options[:direct_upload]
39
+ merged_input_options[:data] = {} if merged_input_options[:data].nil?
40
+ merged_input_options[:data]['direct-upload-url'] = Rails.application.routes.url_helpers.rails_direct_uploads_path
41
+ end
42
+ @builder.file_field(attribute_name, merged_input_options)
43
+ end
44
+
45
+ def field_classes(wrapper_options)
46
+ # "form-control is-valid single_deletable_file optional"
47
+ "sdfi-deletable-file__block #{merge_wrapper_options(input_html_options, wrapper_options)[:class].join(' ')}"
48
+ end
49
+
50
+ def change_file_text
51
+ I18n.t('simple_form_bs5_file_input.replace_file')
52
+ end
53
+
54
+ def field_id
55
+ "#{object_name}_#{reflection_or_attribute_name}"
56
+ end
57
+
58
+ def existing_file_name_or_default_text
59
+ if should_display_file?
60
+ "#{file_attachment.filename}"
61
+ end
62
+ end
63
+
64
+ def input_hidden_name
65
+ "#{@builder.object_name}[#{attribute_name.to_s}_delete]"
66
+ end
67
+
68
+ def input_hidden_value
69
+ "value='true'" if @builder.object.send("#{attribute_name}_delete") == 'true'
70
+ end
71
+
72
+ private
73
+
74
+ def file_attachment
75
+ @builder.object.send("#{attribute_name}_attachment")
76
+ end
77
+
78
+ def should_display_file?
79
+ file_attachment.present?
80
+ end
81
+
82
+ def preview_image_width
83
+ options[:preview] == true ? default_preview_image_width : options[:preview].to_i
84
+ end
85
+
86
+ def preview_image_tag
87
+ if should_display_file? && file_attachment&.variable?
88
+ image_tag(file_attachment.variant(resize: "#{preview_image_width}x").processed.url, class: 'img-fluid img-thumbnail', width: preview_image_width)
89
+ end
90
+ end
91
+
92
+ def default_preview_image_width
93
+ 1000
94
+ end
95
+ end
@@ -0,0 +1,3 @@
1
+ module SimpleFormBs5FileInput
2
+ VERSION = "0.0.1".freeze
3
+ end
@@ -0,0 +1,40 @@
1
+ require 'has_one_attached_deletable'
2
+ require 'simple_form_bs5_file_input/single_deletable_file_input'
3
+
4
+ module SimpleFormBs5FileInput
5
+ def self.add_paths!
6
+ Sprockets.append_path stylesheets_path
7
+ Sprockets.append_path images_path
8
+ Sprockets.append_path javascripts_path
9
+ end
10
+
11
+ def self.add_locales!
12
+ I18n.load_path += Dir["#{root_path}/config/locales/*.yml"]
13
+ end
14
+
15
+ private
16
+
17
+ def self.stylesheets_path
18
+ File.join assets_path, 'stylesheets'
19
+ end
20
+
21
+ def self.images_path
22
+ File.join assets_path, 'images'
23
+ end
24
+
25
+ def self.javascripts_path
26
+ File.join assets_path, 'javascripts'
27
+ end
28
+
29
+ def self.assets_path
30
+ @assets_path ||= File.join root_path, 'assets'
31
+ end
32
+
33
+ def self.root_path
34
+ @root_path ||= File.expand_path '..', File.dirname(__FILE__)
35
+ end
36
+
37
+ end
38
+
39
+ SimpleFormBs5FileInput.add_paths!
40
+ SimpleFormBs5FileInput.add_locales!
@@ -0,0 +1,25 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "simple_form_bs5_file_input/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'simple_form_bs5_file_input'
7
+ s.version = SimpleFormBs5FileInput::VERSION
8
+ s.summary = "Simple Form BS5 File Input"
9
+ s.description = "Improve Simple Form basic input field, add controls/preview on the field."
10
+ s.authors = ["Pierre-andré Boissinot"]
11
+ s.email = 'pa@boissinot.paris'
12
+ s.files = Dir.chdir(File.expand_path('..', __FILE__)) do
13
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
14
+ end
15
+ s.require_paths = ['lib']
16
+ s.homepage =
17
+ 'https://github.com/noesya/simple_form_bs5_file_input'
18
+ s.license = 'MIT'
19
+
20
+ s.add_dependency "rails"
21
+ s.add_dependency "simple_form"
22
+
23
+ s.add_development_dependency "listen"
24
+ s.add_development_dependency "sqlite3"
25
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_form_bs5_file_input
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Pierre-andré Boissinot
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-10-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: simple_form
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: listen
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sqlite3
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Improve Simple Form basic input field, add controls/preview on the field.
70
+ email: pa@boissinot.paris
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - ".eslintrc.yml"
76
+ - ".sass-lint.yml"
77
+ - Gemfile
78
+ - Gemfile.lock
79
+ - LICENSE
80
+ - README.md
81
+ - Rakefile
82
+ - assets/images/icon-cancel.svg
83
+ - assets/javascripts/simple_form_bs5_file_input.js
84
+ - assets/stylesheets/simple_form_bs5_file_input.sass
85
+ - config/locales/en.yml
86
+ - config/locales/fr.yml
87
+ - lib/has_one_attached_deletable.rb
88
+ - lib/simple_form_bs5_file_input.rb
89
+ - lib/simple_form_bs5_file_input/single_deletable_file_input.rb
90
+ - lib/simple_form_bs5_file_input/version.rb
91
+ - simple_form_bs5_file_input.gemspec
92
+ homepage: https://github.com/noesya/simple_form_bs5_file_input
93
+ licenses:
94
+ - MIT
95
+ metadata: {}
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubygems_version: 3.1.4
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: Simple Form BS5 File Input
115
+ test_files: []