dynamic_scaffold 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +12 -0
- data/app/assets/javascripts/dynamic_scaffold.js +2 -1
- data/app/assets/javascripts/dynamic_scaffold/image.js +37 -0
- data/app/assets/javascripts/dynamic_scaffold/sorter.js +10 -4
- data/app/assets/stylesheets/dynamic_scaffold/bootstrap4.scss +6 -1
- data/app/assets/stylesheets/dynamic_scaffold/resplist.scss +4 -1
- data/app/views/dynamic_scaffold/bootstrap/_form.html.erb +16 -0
- data/lib/dynamic_scaffold/config.rb +3 -0
- data/lib/dynamic_scaffold/controller_utilities.rb +4 -1
- data/lib/dynamic_scaffold/form/item/carrier_wave_image.rb +31 -0
- data/lib/dynamic_scaffold/icons/fontawesome.rb +2 -0
- data/lib/dynamic_scaffold/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c40fe45194a04923ed48fbb0d6efb18167fba2cd0af2220d23981ec0128fca8b
|
4
|
+
data.tar.gz: 3ecda8f9b0391686716eb10c151bdfa688b7b84e2b2ca48e8cbc02d99478205c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a4851bb43b47f7d4d181d4f49e21ebfc2268df8cd29b5d1477007f992be0c0d5d0b1394621fc8c71f8b7e58530b5b64f639dd3b3ccd21fd6606ef6015c8800db
|
7
|
+
data.tar.gz: ff879c9a5f4fae140aeec1c2a2212ad705adb8bf7f176375406c5dfc8f9c137195847329acc48ca36dc43bff4a3f0f8348e5cc13b47d54597273e7862a3d490d
|
data/README.md
CHANGED
@@ -227,6 +227,14 @@ class ShopController < ApplicationController
|
|
227
227
|
config.form.item(:collection_check_boxes, :state_ids, State.all, :id, :name)
|
228
228
|
config.form.item(:collection_radio_buttons, :status, Shop.statuses.map{|k, _v| [k, k.titleize]}, :first, :last)
|
229
229
|
|
230
|
+
# You can add an image uploader with preview to the form. The save and remove part to the model corresponds to [carrierwave](https://github.com/carrierwaveuploader/carrierwave).
|
231
|
+
# In the example below, you need to mount the carrierwave uploader on the thumb column of the model.
|
232
|
+
#
|
233
|
+
# class Shop < ApplicationRecord
|
234
|
+
# mount_uploader :thumb, ShopThumbUploader
|
235
|
+
#
|
236
|
+
config.form.item(:carrierwave_image, :thumb, preview_max_size: {width: '300px', height: '300px'})
|
237
|
+
|
230
238
|
# If you want to display more free form field, use block.
|
231
239
|
# The block is executed in the context of view, so you can call the method of view.
|
232
240
|
config.form.item :block, :free do |form, field|
|
@@ -506,5 +514,9 @@ end
|
|
506
514
|
* We use rspec for test.
|
507
515
|
* Check code with [rubocop](https://github.com/bbatsov/rubocop).
|
508
516
|
|
517
|
+
### Development hints.
|
518
|
+
|
519
|
+
Please support both Bootstrap 3/4. You can change CSS to Bootstrap3 by registering `bootstrap=3` in cookie in the sample page.
|
520
|
+
|
509
521
|
## License
|
510
522
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
@@ -0,0 +1,37 @@
|
|
1
|
+
document.addEventListener('dynamic_scaffold:load', function (){
|
2
|
+
const inputs = document.querySelectorAll('.dynamicScaffoldJs-image')
|
3
|
+
Array.prototype.forEach.call(inputs, function(input){
|
4
|
+
// initialize
|
5
|
+
const wrapper = input.closest('.dynamicScaffoldJs-image-wrapper')
|
6
|
+
const preview = wrapper.querySelector('.dynamicScaffoldJs-image-preview')
|
7
|
+
const img = preview.querySelector('img')
|
8
|
+
|
9
|
+
// hide on non image
|
10
|
+
if(!img.getAttribute('src')){
|
11
|
+
preview.style.display = 'none'
|
12
|
+
}
|
13
|
+
|
14
|
+
// delete event
|
15
|
+
const button = preview.querySelector('.dynamicScaffoldJs-image-remove')
|
16
|
+
const flag = wrapper.querySelector('.dynamicScaffoldJs-image-remove-flag')
|
17
|
+
button.addEventListener('click', function(e){
|
18
|
+
preview.style.display = 'none'
|
19
|
+
flag.disabled = false
|
20
|
+
input.value = ''
|
21
|
+
})
|
22
|
+
|
23
|
+
// change event
|
24
|
+
input.addEventListener('change', function(e){
|
25
|
+
const reader = new FileReader();
|
26
|
+
reader.onload = function (e) {
|
27
|
+
img.src = e.target.result
|
28
|
+
preview.style.display = 'block'
|
29
|
+
flag.disabled = true
|
30
|
+
}
|
31
|
+
|
32
|
+
if(input.files.length){
|
33
|
+
reader.readAsDataURL(input.files[0])
|
34
|
+
}
|
35
|
+
})
|
36
|
+
})
|
37
|
+
})
|
@@ -8,14 +8,20 @@ document.addEventListener('dynamic_scaffold:load', function(){
|
|
8
8
|
sourceRect = source.getBoundingClientRect()
|
9
9
|
targetRect = target.getBoundingClientRect()
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
|
12
|
+
// Find the distance between two points and calculate the animation duration.
|
13
13
|
const durationBase = 200
|
14
|
+
const distance = Math.sqrt(
|
15
|
+
Math.pow(targetRect.left - sourceRect.left, 2 ) + Math.pow( targetRect.top - sourceRect.top, 2 )
|
16
|
+
)
|
14
17
|
const durationFactor = Math.abs(distance) * 0.03
|
15
18
|
const duration = Math.min(durationBase + durationFactor, 600)
|
16
|
-
|
17
19
|
source.style.transition = 'all ' + duration + 'ms cubic-bezier(1.0, 0, 0.25, 1.0)'
|
18
|
-
|
20
|
+
|
21
|
+
//Calculate the duration according to the moving distance.
|
22
|
+
const y = targetRect.top - sourceRect.top
|
23
|
+
const x = targetRect.left - sourceRect.left
|
24
|
+
source.style.transform = 'translate(' + x + 'px, ' + y + 'px)'
|
19
25
|
}))
|
20
26
|
}
|
21
27
|
|
@@ -4,6 +4,7 @@
|
|
4
4
|
$dynamic_scaffold_primary: #007bff !default;
|
5
5
|
$dynamic_scaffold_secondary: #868e96 !default;
|
6
6
|
$dynamic_scaffold_warning: #ffc107 !default;
|
7
|
+
$dynamic_scaffold_danger: #dc3545 !default;
|
7
8
|
|
8
9
|
.btn-outline-primary, .btn-outline-secondary, .btn-outline-warning{
|
9
10
|
background-color: #fff;
|
@@ -29,7 +30,11 @@ $dynamic_scaffold_warning: #ffc107 !default;
|
|
29
30
|
fill: $dynamic_scaffold_warning;
|
30
31
|
}
|
31
32
|
|
32
|
-
.btn-outline-
|
33
|
+
.btn-outline-danger path{
|
34
|
+
fill: $dynamic_scaffold_danger;
|
35
|
+
}
|
36
|
+
|
37
|
+
.btn-outline-warning:hover, .btn-outline-danger:hover{
|
33
38
|
path{
|
34
39
|
fill: #fff;
|
35
40
|
}
|
@@ -49,10 +49,12 @@
|
|
49
49
|
clear: both;
|
50
50
|
}
|
51
51
|
|
52
|
-
|
52
|
+
.resplist {
|
53
53
|
list-style: none;
|
54
54
|
padding: 0;
|
55
55
|
border-collapse: separate;
|
56
|
+
display: flex;
|
57
|
+
flex-wrap: wrap;
|
56
58
|
}
|
57
59
|
|
58
60
|
.resplist-striped .resplist-row:nth-child(odd) {
|
@@ -114,6 +116,7 @@ ul.resplist {
|
|
114
116
|
background-color: #fff;
|
115
117
|
border-top: 1px solid #dddddd;
|
116
118
|
padding: 0;
|
119
|
+
width: 100%;
|
117
120
|
}
|
118
121
|
|
119
122
|
.resplist-item-xs {
|
@@ -26,6 +26,22 @@
|
|
26
26
|
<%end%>
|
27
27
|
</div>
|
28
28
|
<%end%>
|
29
|
+
<% elsif elem.type? :carrierwave_image %>
|
30
|
+
<%- image = form.object.public_send(elem.name) -%>
|
31
|
+
<div class="dynamicScaffoldJs-image-wrapper">
|
32
|
+
<div class="dynamicScaffoldJs-image-preview panel panel-default card mb-1" style="<%= elem.preview_image_style %>">
|
33
|
+
<div class="text-right panel-heading card-header">
|
34
|
+
<button type="button" class="btn btn-outline-danger btn-danger btn-sm dynamicScaffoldJs-image-remove">
|
35
|
+
<%= dynamic_scaffold_icon :times %>
|
36
|
+
</button>
|
37
|
+
</div>
|
38
|
+
<img src="<%= image.url if image.file.present? %>" alt="" class="img-responsive img-fluid">
|
39
|
+
</div>
|
40
|
+
<%= form.hidden_field "remove_#{elem.name}", value: "1", disabled:"disabled", class: 'dynamicScaffoldJs-image-remove-flag'%>
|
41
|
+
<%= elem.render(self, form, 'form-control-file dynamicScaffoldJs-image') do |attr|%>
|
42
|
+
<%= form.file_field(elem.name, attr) %>
|
43
|
+
<%end%>
|
44
|
+
</div>
|
29
45
|
<% else %>
|
30
46
|
<%= elem.render(self, form, class_names('form-control', {'is-invalid': @record.errors[elem.proxy_field.name].any?})) %>
|
31
47
|
<% end %>
|
@@ -263,6 +263,9 @@ module DynamicScaffold
|
|
263
263
|
when
|
264
264
|
:block then
|
265
265
|
item = Form::Item::Block.new(@config, type, *args, block)
|
266
|
+
when
|
267
|
+
:carrierwave_image then
|
268
|
+
item = Form::Item::CarrierWaveImage.new(@config, type, *args)
|
266
269
|
else
|
267
270
|
raise DynamicScaffold::Error::Config, "Unknown form item type #{type}"
|
268
271
|
end
|
@@ -30,7 +30,10 @@ module DynamicScaffold
|
|
30
30
|
|
31
31
|
# Get paramters for update record.
|
32
32
|
def update_values
|
33
|
-
permitting = dynamic_scaffold.form.items
|
33
|
+
permitting = dynamic_scaffold.form.items
|
34
|
+
.map(&:strong_parameter)
|
35
|
+
.concat(dynamic_scaffold.form.permit_params)
|
36
|
+
.flatten
|
34
37
|
values = params
|
35
38
|
.require(dynamic_scaffold.model.name.underscore)
|
36
39
|
.permit(*permitting)
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module DynamicScaffold
|
2
|
+
module Form
|
3
|
+
module Item
|
4
|
+
class CarrierWaveImage < Base
|
5
|
+
def initialize(config, type, name, options = {})
|
6
|
+
super(config, type, name, {})
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def preview_image_style
|
11
|
+
max_size = @options[:preview_max_size]
|
12
|
+
return '' unless max_size
|
13
|
+
|
14
|
+
''.tap do |s|
|
15
|
+
s << "max-width: #{max_size[:width]};" if max_size[:width]
|
16
|
+
s << "max-height: #{max_size[:height]};" if max_size[:height]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def render(_view, _form, classnames = nil)
|
21
|
+
html_attributes = build_html_attributes(classnames)
|
22
|
+
yield(html_attributes)
|
23
|
+
end
|
24
|
+
|
25
|
+
def strong_parameter
|
26
|
+
[@name, "remove_#{@name}"]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -41,6 +41,8 @@ Rails.application.config.dynamic_scaffold.icons = proc do |name|
|
|
41
41
|
DynamicScaffold::Fontawesome.inline_svg('angle-double-up.svg')
|
42
42
|
when :bottom then
|
43
43
|
DynamicScaffold::Fontawesome.inline_svg('angle-double-down.svg')
|
44
|
+
when :times then
|
45
|
+
DynamicScaffold::Fontawesome.inline_svg('times.svg')
|
44
46
|
else
|
45
47
|
raise DynamicScaffold::Error::InvalidIcon, "Unknown icon type #{name} specified."
|
46
48
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dynamic_scaffold
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masamoto Miyata
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-05-
|
11
|
+
date: 2018-05-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: classnames-rails-view
|
@@ -226,6 +226,7 @@ files:
|
|
226
226
|
- app/assets/javascripts/dynamic_scaffold.js
|
227
227
|
- app/assets/javascripts/dynamic_scaffold/common.js
|
228
228
|
- app/assets/javascripts/dynamic_scaffold/delete.js
|
229
|
+
- app/assets/javascripts/dynamic_scaffold/image.js
|
229
230
|
- app/assets/javascripts/dynamic_scaffold/pagination.js
|
230
231
|
- app/assets/javascripts/dynamic_scaffold/sorter.js
|
231
232
|
- app/assets/stylesheets/dynamic_scaffold/bootstrap3.scss
|
@@ -259,6 +260,7 @@ files:
|
|
259
260
|
- lib/dynamic_scaffold/error/invalid_icon.rb
|
260
261
|
- lib/dynamic_scaffold/form/item/base.rb
|
261
262
|
- lib/dynamic_scaffold/form/item/block.rb
|
263
|
+
- lib/dynamic_scaffold/form/item/carrier_wave_image.rb
|
262
264
|
- lib/dynamic_scaffold/form/item/single_option.rb
|
263
265
|
- lib/dynamic_scaffold/form/item/two_options.rb
|
264
266
|
- lib/dynamic_scaffold/form/item/two_options_with_block.rb
|