interview 0.0.8 → 0.0.9
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/lib/generators/interview/install/templates/application.js +1 -1
- data/lib/generators/interview/install/templates/bootstrap_interview.css.scss +12 -0
- data/lib/generators/interview/install/templates/interview.js.coffee +21 -26
- data/lib/interview/attribute.rb +9 -6
- data/lib/interview/button.rb +29 -0
- data/lib/interview/collapse_container.rb +13 -2
- data/lib/interview/dropdown.rb +3 -2
- data/lib/interview/form.rb +2 -2
- data/lib/interview/image_attribute.rb +67 -38
- data/lib/interview/image_gallery_attribute.rb +18 -13
- data/lib/interview/link.rb +5 -2
- data/lib/interview/media_object.rb +2 -2
- data/lib/interview/nested_form.rb +19 -4
- data/lib/interview/nested_form_add_images.rb +33 -0
- data/lib/interview/progress_bar.rb +25 -0
- data/lib/interview/text.rb +2 -2
- data/lib/interview/version.rb +1 -1
- data/lib/interview.rb +26 -15
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a79c351a953b407088c70c6686535f16980de03e
|
4
|
+
data.tar.gz: 2715694c6c5444764247942612506e19921b4390
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e12ba218332bfac951c2d76f15262cd50b1e1f7f48f4299955441b6aefa3912e49562cfe20997ad688b86d8ed25f24bee13fa0062cc1c4bd131380695e31dd2f
|
7
|
+
data.tar.gz: 671e31446ed9a9843030ddb389671ab48aa842e31f2281c02585890a3c01e49576177f432439a57262a1c604d10da1029f9bcbfbd134a9bdf2732e85a40d4e87
|
@@ -123,4 +123,16 @@ $nav-stacked-link-padding-level2: 5px 15px 5px 45px !default;
|
|
123
123
|
vertical-align: middle;
|
124
124
|
margin-right: 5px;
|
125
125
|
margin-bottom: 5px;
|
126
|
+
}
|
127
|
+
|
128
|
+
.nested_form_container {
|
129
|
+
margin: 15px 0px;
|
130
|
+
}
|
131
|
+
|
132
|
+
.nested_form {
|
133
|
+
margin-top: 15px;
|
134
|
+
}
|
135
|
+
|
136
|
+
.progress-bar {
|
137
|
+
height: 20px;
|
126
138
|
}
|
@@ -76,46 +76,44 @@ jQuery ->
|
|
76
76
|
$($(this).data('target')).collapse('toggle')
|
77
77
|
|
78
78
|
$('.img-link').click (e) ->
|
79
|
-
|
79
|
+
e.preventDefault()
|
80
|
+
links = $(this).closest('.image-gallery').find('.img-link')
|
80
81
|
target = event.target || event.srcElement
|
81
82
|
link = if target.src then target.parentNode else target
|
82
83
|
options = { index: link, event: e }
|
83
84
|
blueimp.Gallery(links, options)
|
84
85
|
|
85
|
-
$('.
|
86
|
+
$('.upload_image').fileupload
|
86
87
|
add: (e, data) ->
|
87
88
|
types = /(\.|\/)(gif|jpe?g|png|mov|mpeg|mpeg4|avi)$/i
|
88
89
|
file = data.files[0]
|
89
90
|
if types.test(file.type) || types.test(file.name)
|
90
|
-
|
91
|
-
$('
|
92
|
-
|
93
|
-
$("input[name='_method']").attr('name', 'method')
|
91
|
+
$(this).closest('.image_attribute_container').find('.progress').collapse('show')
|
92
|
+
$("input[name='_method']").attr('name', '__method')
|
94
93
|
data.submit()
|
95
|
-
$("input[name='
|
94
|
+
$("input[name='__method']").attr('name', '_method')
|
96
95
|
else
|
97
96
|
alert("#{file.name} is not a gif, jpg or png image file")
|
98
97
|
progress: (e, data) ->
|
99
|
-
|
100
|
-
|
101
|
-
data.context.find('.bar').css('width', progress + '%')
|
98
|
+
progress = parseInt(data.loaded / data.total * 100, 10)
|
99
|
+
$(this).closest('.image_attribute_container').find('.bar').css('width', progress + '%')
|
102
100
|
done: (e, data) ->
|
103
|
-
$('
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
$('.multiple-image-upload').fileupload
|
101
|
+
$(this).closest('.image_attribute_container').find('.upload_buffer_id').attr('value', data.result.id)
|
102
|
+
$(this).closest('.image_attribute_container').find('.image').attr('src', data.result.thumb_url)
|
103
|
+
|
104
|
+
$('.nested_form_add_images').fileupload
|
109
105
|
add: (e, data) ->
|
110
106
|
types = /(\.|\/)(gif|jpe?g|png|mov|mpeg|mpeg4|avi)$/i
|
111
107
|
file = data.files[0]
|
112
108
|
if types.test(file.type) || types.test(file.name)
|
113
|
-
|
114
|
-
$('
|
115
|
-
|
116
|
-
|
109
|
+
tmpl_data = { index: new Date().getTime() }
|
110
|
+
data.context = $(this).closest('.nested_form_container').find('.nested_form_script').tmpl(tmpl_data)
|
111
|
+
$(this).closest('.nested_form_container').append(data.context)
|
112
|
+
data.context.find('.progress').collapse('show')
|
113
|
+
bind_remove_links()
|
114
|
+
$("input[name='_method']").attr('name', 'x_method')
|
117
115
|
data.submit()
|
118
|
-
$("input[name='
|
116
|
+
$("input[name='x_method']").attr('name', '_method')
|
119
117
|
else
|
120
118
|
alert("#{file.name} is not a gif, jpg or png image file")
|
121
119
|
progress: (e, data) ->
|
@@ -123,8 +121,5 @@ jQuery ->
|
|
123
121
|
progress = parseInt(data.loaded / data.total * 100, 10)
|
124
122
|
data.context.find('.bar').css('width', progress + '%')
|
125
123
|
done: (e, data) ->
|
126
|
-
context
|
127
|
-
|
128
|
-
ids = JSON.parse($('.image-ids').attr('value'))
|
129
|
-
ids.push data.result.id
|
130
|
-
$('.image-ids').attr('value', JSON.stringify(ids))
|
124
|
+
data.context.find('.upload_buffer_id').attr('value', data.result.id)
|
125
|
+
data.context.find('.image').attr('src', data.result.thumb_url)
|
data/lib/interview/attribute.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
module Interview
|
2
2
|
class Attribute < Control
|
3
3
|
|
4
|
-
attr_accessor :method, :caption, :style, :link, :nil_value, :hide_caption, :
|
5
|
-
:only_for, :align, :on_changed, :html_class, :surrounding_tag
|
4
|
+
attr_accessor :method, :caption, :style, :link, :nil_value, :hide_caption, :caption_as_placeholder,
|
5
|
+
:hide_tooltip, :only_for, :align, :on_changed, :html_class, :surrounding_tag
|
6
6
|
|
7
7
|
def initialize(params={})
|
8
|
-
@html_class = []
|
9
8
|
super
|
9
|
+
@html_class = []
|
10
|
+
@html_class << params[:html_class] if params[:html_class]
|
10
11
|
end
|
11
12
|
|
12
13
|
def value
|
@@ -49,7 +50,9 @@ module Interview
|
|
49
50
|
end
|
50
51
|
|
51
52
|
def render_write
|
52
|
-
|
53
|
+
opts = {class: 'form-control'}
|
54
|
+
opts[:placeholder] = caption if @caption_as_placeholder
|
55
|
+
return form_builder.text_field @method, opts
|
53
56
|
end
|
54
57
|
|
55
58
|
protected
|
@@ -82,7 +85,7 @@ module Interview
|
|
82
85
|
html = Builder::XmlMarkup.new(indent: 2)
|
83
86
|
html.div class: 'form-group' do
|
84
87
|
|
85
|
-
html.div class: 'col-xs-3' if @hide_caption and align == 'horizontal'
|
88
|
+
html.div class: 'col-xs-3' if (@hide_caption or @caption_as_placeholder) and align == 'horizontal'
|
86
89
|
render_form_label(html)
|
87
90
|
|
88
91
|
if align == 'horizontal'
|
@@ -101,7 +104,7 @@ module Interview
|
|
101
104
|
|
102
105
|
def render_form_label(html)
|
103
106
|
align = @align || find_attribute(:align)
|
104
|
-
html_opts = if @hide_caption or align == 'inline'
|
107
|
+
html_opts = if @hide_caption or @caption_as_placeholder or align == 'inline'
|
105
108
|
{ class: 'sr-only' }
|
106
109
|
elsif align == 'horizontal'
|
107
110
|
{ class: 'col-xs-3 control-label' }
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Interview
|
2
|
+
class Button < Control
|
3
|
+
include HasControls
|
4
|
+
|
5
|
+
attr_accessor :caption, :name, :style, :submit
|
6
|
+
attr_reader :html_class
|
7
|
+
|
8
|
+
def initialize(params={})
|
9
|
+
@html_class = []
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def render
|
14
|
+
html_class = @html_class
|
15
|
+
if @style.to_s == 'primary'
|
16
|
+
html_class << 'btn btn-primary'
|
17
|
+
else
|
18
|
+
html_class << 'btn btn-default'
|
19
|
+
end
|
20
|
+
|
21
|
+
if @submit
|
22
|
+
h.submit_tag @caption, name: @name, class: @html_class.join(' ')
|
23
|
+
else
|
24
|
+
h.button_tag @caption, name: @name, class: @html_class.join(' ')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -6,10 +6,21 @@ module Interview
|
|
6
6
|
|
7
7
|
def render
|
8
8
|
html = Builder::XmlMarkup.new
|
9
|
+
if @caption
|
10
|
+
link = Interview::Link.new(caption: @caption)
|
11
|
+
controls = @controls
|
12
|
+
else
|
13
|
+
link = @controls.first
|
14
|
+
controls = @controls[1..-1]
|
15
|
+
end
|
16
|
+
link.url = '#'
|
17
|
+
link.html_class << 'collapse_link'
|
18
|
+
link.html_data[:toggle] = 'collapse'
|
9
19
|
new_id = Time.now.to_f.to_s.delete('.')
|
10
|
-
|
20
|
+
link.html_data[:target] = "##{new_id}"
|
21
|
+
html << link.render
|
11
22
|
html.div id: new_id, class: 'panel-collapse collapse' do
|
12
|
-
|
23
|
+
controls.each do |control|
|
13
24
|
html << control.render
|
14
25
|
end
|
15
26
|
end
|
data/lib/interview/dropdown.rb
CHANGED
@@ -2,7 +2,7 @@ module Interview
|
|
2
2
|
class Dropdown < Control
|
3
3
|
include HasControls
|
4
4
|
|
5
|
-
attr_accessor :image, :caption, :style, :html_class
|
5
|
+
attr_accessor :image, :caption, :style, :html_class, :container_tag
|
6
6
|
|
7
7
|
def initialize(params={})
|
8
8
|
@html_class = []
|
@@ -10,10 +10,11 @@ module Interview
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def render
|
13
|
+
container_tag = @container_tag || 'div'
|
13
14
|
html = Builder::XmlMarkup.new
|
14
15
|
html_class = @html_class.dup
|
15
16
|
html_class << 'dropdown'
|
16
|
-
html.
|
17
|
+
html.tag! container_tag, class: html_class.join(' ') do
|
17
18
|
html_class = 'dropdown-toggle'
|
18
19
|
html_class += ' btn btn-default' if @style == 'button'
|
19
20
|
html.a class: html_class, href: '#', :'data-toggle' => 'dropdown' do
|
data/lib/interview/form.rb
CHANGED
@@ -2,7 +2,7 @@ module Interview
|
|
2
2
|
class Form < Control
|
3
3
|
include HasControls
|
4
4
|
|
5
|
-
attr_accessor :skip_submit, :multi_create, :align, :redirect_to
|
5
|
+
attr_accessor :skip_submit, :submit_label, :multi_create, :align, :redirect_to
|
6
6
|
attr_reader :form_builder
|
7
7
|
|
8
8
|
def render
|
@@ -41,7 +41,7 @@ module Interview
|
|
41
41
|
|
42
42
|
def render_submit(html)
|
43
43
|
if not @skip_submit
|
44
|
-
html << form_builder.submit(class: 'btn btn-primary')
|
44
|
+
html << form_builder.submit(@submit_label, class: 'btn btn-primary')
|
45
45
|
if @multi_create || find_attribute(:multi_create)
|
46
46
|
html.text! ' '
|
47
47
|
html << h.check_box_tag('new_record', '1', true)
|
@@ -9,65 +9,94 @@ module Interview
|
|
9
9
|
attr_accessor :object, :submethod, :image_style, :hide_if_not_exists
|
10
10
|
|
11
11
|
def render_read
|
12
|
-
submethod = @submethod || 'attachment'
|
13
12
|
image_style = @image_style || :thumb
|
14
|
-
object = @object || find_attribute(:object)
|
15
|
-
image = value || object.association(@method).build
|
16
13
|
|
17
|
-
|
18
|
-
return '' if not attachment.exists? and @hide_if_not_exists
|
14
|
+
return '' if value.nil? and @hide_if_not_exists
|
19
15
|
|
20
16
|
html = Builder::XmlMarkup.new
|
21
17
|
opts = {class: "image_#{image_style}"}
|
22
18
|
opts[:class] += ' ' + @html_class.join(' ') unless @html_class.empty? or @surrounding_tag
|
23
19
|
html.div opts do
|
24
|
-
|
20
|
+
if value.nil?
|
21
|
+
html << h.image_tag('missing_thumb.png', class: 'image img-responsive')
|
22
|
+
else
|
23
|
+
html << h.image_tag(value.url(image_style), class: 'image img-responsive')
|
24
|
+
end
|
25
25
|
end
|
26
26
|
return html.target!
|
27
27
|
end
|
28
28
|
|
29
29
|
def render_write
|
30
|
-
object = @object || find_attribute(:object)
|
31
|
-
submethod = @submethod || 'attachment'
|
32
30
|
image_style = @image_style || :thumb
|
33
|
-
image = object.send(@method) || object.association(@method).build
|
34
|
-
attachment = image.send(submethod)
|
35
|
-
model = image.class.model_name.singular
|
36
31
|
|
37
32
|
html = Builder::XmlMarkup.new
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
end
|
44
|
-
|
45
|
-
html.div class: 'inline-block' do
|
46
|
-
html.span class: "btn btn-default fileinput-button" do
|
47
|
-
html.span "Select file..."
|
48
|
-
html << h.file_field_tag("#{model}[#{submethod}]", class: 'image-upload',
|
49
|
-
data: {url: "/#{model.pluralize}.json", type: 'POST'})
|
33
|
+
html.div class: 'image_attribute_container' do
|
34
|
+
unless value.nil? and @hide_if_not_exists
|
35
|
+
html.div class: 'inline-block' do
|
36
|
+
html << h.image_tag(value.url(image_style), class: 'image img-responsive')
|
37
|
+
end
|
50
38
|
end
|
51
39
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
60
|
-
|
61
|
-
html.script id: 'upload-progress-script', type: 'text/x-tmpl' do
|
62
|
-
html.div class: 'upload' do
|
63
|
-
html.text! "{%=o.name%}"
|
64
|
-
html.div class: 'progress' do
|
65
|
-
html.div '', class: 'progress-bar bar', style: 'width: 0%'
|
40
|
+
html.div class: 'inline-block' do
|
41
|
+
html.div class: "clearfix" do
|
42
|
+
html.span class: "btn btn-default fileinput-button" do
|
43
|
+
html.span "Bild hochladen" # todo
|
44
|
+
html << h.file_field_tag("upload_buffer[attachment]", class: 'upload_image',
|
45
|
+
data: {url: "/upload_buffers.json", type: 'POST'})
|
46
|
+
end
|
66
47
|
end
|
48
|
+
html << Interview::ProgressBar.new(hidden: true).render
|
49
|
+
html << form_builder.hidden_field(:upload_buffer_id, class: 'upload_buffer_id')
|
50
|
+
|
51
|
+
# if attachment.exists?
|
52
|
+
# html << form_builder.check_box("destroy_#{@method}")
|
53
|
+
# html.text! ' Datei löschen'
|
54
|
+
# end
|
67
55
|
end
|
68
56
|
end
|
69
|
-
|
70
57
|
return html.target!
|
58
|
+
|
59
|
+
# object = @object || find_attribute(:object)
|
60
|
+
# submethod = @submethod || 'attachment'
|
61
|
+
# image_style = @image_style || :thumb
|
62
|
+
# image = object.send(@method) || object.association(@method).build
|
63
|
+
# attachment = image.send(submethod)
|
64
|
+
# model = image.class.model_name.singular
|
65
|
+
#
|
66
|
+
# html = Builder::XmlMarkup.new
|
67
|
+
#
|
68
|
+
# html << form_builder.hidden_field("#{@method.singularize}_id", class: 'image-id')
|
69
|
+
#
|
70
|
+
# html.div class: 'inline-block' do
|
71
|
+
# html << h.image_tag(attachment.url(image_style), id: 'image-tag')
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# html.div class: 'inline-block' do
|
75
|
+
# html.span class: "btn btn-default fileinput-button" do
|
76
|
+
# html.span "Select file..."
|
77
|
+
# html << h.file_field_tag("#{model}[#{submethod}]", class: 'image-upload',
|
78
|
+
# data: {url: "/#{model.pluralize}.json", type: 'POST'})
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
# # if attachment.exists?
|
82
|
+
# # html << form_builder.check_box("destroy_#{@method}")
|
83
|
+
# # html.text! ' Datei löschen'
|
84
|
+
# # end
|
85
|
+
# end
|
86
|
+
#
|
87
|
+
# html.div id: 'upload-progress' do
|
88
|
+
# end
|
89
|
+
#
|
90
|
+
# html.script id: 'upload-progress-script', type: 'text/x-tmpl' do
|
91
|
+
# html.div class: 'upload' do
|
92
|
+
# html.text! "{%=o.name%}"
|
93
|
+
# html.div class: 'progress' do
|
94
|
+
# html.div '', class: 'progress-bar bar', style: 'width: 0%'
|
95
|
+
# end
|
96
|
+
# end
|
97
|
+
# end
|
98
|
+
#
|
99
|
+
# return html.target!
|
71
100
|
end
|
72
101
|
|
73
102
|
end
|
@@ -25,14 +25,14 @@ module Interview
|
|
25
25
|
|
26
26
|
html << form_builder.hidden_field("#{@method.singularize}_ids", class: 'image-ids')
|
27
27
|
|
28
|
-
render_gallery(html, images, submethod, image_style, @light_box_image_style)
|
29
|
-
|
30
|
-
light_box_image_url = @light_box_image_style ? "#{@light_box_image_style}_url" : 'url'
|
31
|
-
html.script id: 'image-thumb-script', type: 'text/x-tmpl' do
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
28
|
+
# render_gallery(html, images, submethod, image_style, @light_box_image_style)
|
29
|
+
#
|
30
|
+
# light_box_image_url = @light_box_image_style ? "#{@light_box_image_style}_url" : 'url'
|
31
|
+
# html.script id: 'image-thumb-script', type: 'text/x-tmpl' do
|
32
|
+
# html.a href: "{%=o.#{light_box_image_url}%}", class: 'img-link' do
|
33
|
+
# html.img class: 'img-thumb', src: "{%=o.thumb_url%}"
|
34
|
+
# end
|
35
|
+
# end
|
36
36
|
|
37
37
|
html.div class: "clearfix" do
|
38
38
|
html.span class: "btn btn-default fileinput-button" do
|
@@ -46,10 +46,15 @@ module Interview
|
|
46
46
|
end
|
47
47
|
|
48
48
|
html.script id: 'upload-progress-script', type: 'text/x-tmpl' do
|
49
|
-
html.div
|
50
|
-
html.
|
51
|
-
|
52
|
-
|
49
|
+
html.div do
|
50
|
+
html.div class: 'inline-block' do
|
51
|
+
html.img class: 'img-thumb', src: '/assets/missing_180x180.png'
|
52
|
+
end
|
53
|
+
html.div class: 'inline-block' do
|
54
|
+
html.text! "{%=o.name%}"
|
55
|
+
html.div class: 'progress' do
|
56
|
+
html.div '', class: 'progress-bar bar', style: 'width: 0%'
|
57
|
+
end
|
53
58
|
end
|
54
59
|
end
|
55
60
|
end
|
@@ -63,7 +68,7 @@ module Interview
|
|
63
68
|
def render_gallery(html, images, submethod, image_style, light_box_image_style)
|
64
69
|
html.div class: 'image-gallery' do
|
65
70
|
images.each do |image|
|
66
|
-
html.a href: image.send(submethod).url(light_box_image_style), class: 'img-link' do
|
71
|
+
html.a href: image.send(submethod).url(light_box_image_style), class: 'img-link', title: image.subtitle do
|
67
72
|
html << h.image_tag(image.send(submethod).url(image_style), class: 'img-thumb')
|
68
73
|
end
|
69
74
|
end
|
data/lib/interview/link.rb
CHANGED
@@ -3,11 +3,13 @@ module Interview
|
|
3
3
|
include HasControls
|
4
4
|
|
5
5
|
attr_accessor :image, :caption, :hint, :style, :active,
|
6
|
-
:url, :controller, :object, :action, :http_method, :redirect_to,
|
7
|
-
|
6
|
+
:url, :controller, :object, :action, :http_method, :redirect_to,
|
7
|
+
:nested_resource, :trail
|
8
|
+
attr_reader :url_params, :html_class, :html_data
|
8
9
|
|
9
10
|
def initialize(params={})
|
10
11
|
@html_class = []
|
12
|
+
@html_data = {}
|
11
13
|
@url_params = {}
|
12
14
|
super
|
13
15
|
end
|
@@ -111,6 +113,7 @@ module Interview
|
|
111
113
|
def render_link(url, html_class=[], html_options={})
|
112
114
|
class_string = html_class.join(' ')
|
113
115
|
html_options[:class] = class_string unless html_class.empty?
|
116
|
+
html_options[:data] = @html_data unless @html_data.empty?
|
114
117
|
return h.link_to(url, html_options) do
|
115
118
|
html = Builder::XmlMarkup.new
|
116
119
|
if @controls.empty?
|
@@ -6,11 +6,11 @@ module Interview
|
|
6
6
|
|
7
7
|
def render
|
8
8
|
image_size = @image_size || :thumb
|
9
|
-
object = find_attribute
|
9
|
+
object = find_attribute :object
|
10
10
|
@object = object
|
11
11
|
html = Builder::XmlMarkup.new(indent: 2)
|
12
12
|
html.div class: 'media' do
|
13
|
-
@controls.
|
13
|
+
@controls[0].html_class << 'pull-left' if @controls[0].respond_to? 'html_class'
|
14
14
|
html << @controls.first.render
|
15
15
|
html.div class: 'media-body' do
|
16
16
|
@controls[1].html_class << 'media-heading' if @controls[1].respond_to? 'html_class'
|
@@ -2,23 +2,35 @@ module Interview
|
|
2
2
|
class NestedForm < Control
|
3
3
|
include HasControls
|
4
4
|
|
5
|
-
attr_accessor :polymorphic, :align # todo: align einbauen
|
5
|
+
attr_accessor :polymorphic, :align, :image_based # todo: align einbauen
|
6
6
|
attr_reader :form_builder, :object
|
7
7
|
|
8
8
|
def render
|
9
9
|
assoc_form_builder = find_attribute! :form_builder
|
10
10
|
assoc_method = find_attribute! :assoc_method
|
11
|
-
objects = find_attribute! :objects
|
12
11
|
|
13
12
|
html = Builder::XmlMarkup.new
|
14
|
-
html.div class: '
|
15
|
-
|
13
|
+
html.div class: 'nested_form_container' do
|
14
|
+
if @image_based
|
15
|
+
html << Interview::NestedFormAddImages.new.render
|
16
|
+
end
|
17
|
+
html << assoc_form_builder.fields_for(assoc_method.to_sym) do |form_builder|
|
16
18
|
if @polymorphic
|
17
19
|
render_polymorphic_nested_form(form_builder)
|
18
20
|
else
|
19
21
|
render_nested_form(form_builder)
|
20
22
|
end
|
21
23
|
end
|
24
|
+
html.script class: 'nested_form_script', type: 'text/x-tmpl' do
|
25
|
+
new_object = assoc_form_builder.object.association(assoc_method.to_sym).build # todo: polymorphic add link
|
26
|
+
html << assoc_form_builder.fields_for(assoc_method.to_sym, new_object, :child_index => "${index}") do |form_builder|
|
27
|
+
if @polymorphic
|
28
|
+
render_polymorphic_nested_form(form_builder)
|
29
|
+
else
|
30
|
+
render_nested_form(form_builder)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
22
34
|
end
|
23
35
|
return html.target!
|
24
36
|
end
|
@@ -33,6 +45,9 @@ module Interview
|
|
33
45
|
end
|
34
46
|
html << form_builder.hidden_field(:id)
|
35
47
|
html << form_builder.hidden_field(:_destroy, class: 'nested_form_destroy')
|
48
|
+
if @image_based
|
49
|
+
html << form_builder.hidden_field(:upload_buffer_id, class: 'upload_buffer_id')
|
50
|
+
end
|
36
51
|
end
|
37
52
|
html.target!.html_safe
|
38
53
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Interview
|
2
|
+
class NestedFormAddImages < Control
|
3
|
+
|
4
|
+
attr_accessor :style
|
5
|
+
|
6
|
+
def render
|
7
|
+
if @style and @style.to_sym == :horizontal_form
|
8
|
+
html = Builder::XmlMarkup.new # todo: in eigenes Objekt auslagern?
|
9
|
+
html.div class: 'row' do
|
10
|
+
html.div class: 'col-xs-9 col-xs-offset-3' do
|
11
|
+
html << render_link
|
12
|
+
end
|
13
|
+
end
|
14
|
+
return html.target!
|
15
|
+
else
|
16
|
+
return render_link
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def render_link
|
21
|
+
html = Builder::XmlMarkup.new
|
22
|
+
html.div class: "clearfix" do
|
23
|
+
html.span class: "btn btn-default fileinput-button" do
|
24
|
+
html.span "Bilder hinzufügen" # todo
|
25
|
+
html << h.file_field_tag("upload_buffer[attachment]", class: 'nested_form_add_images',
|
26
|
+
multiple: true, data: {url: "/upload_buffers.json", type: 'POST'})
|
27
|
+
end
|
28
|
+
end
|
29
|
+
return html.target!
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Interview
|
2
|
+
class ProgressBar < Control
|
3
|
+
|
4
|
+
attr_accessor :hidden, :html_class
|
5
|
+
|
6
|
+
def initialize(params={})
|
7
|
+
super
|
8
|
+
@html_class = []
|
9
|
+
@html_class << params[:html_class] if params[:html_class]
|
10
|
+
end
|
11
|
+
|
12
|
+
def render
|
13
|
+
html_class = @html_class
|
14
|
+
html = Builder::XmlMarkup.new
|
15
|
+
opts = { class: "progress" }
|
16
|
+
opts[:class] += " collapse" if @hidden
|
17
|
+
opts[:class] += ' ' + @html_class.join(' ') unless @html_class.empty?
|
18
|
+
html.div opts do
|
19
|
+
html.div '', class: 'progress-bar bar', style: 'width: 0%'
|
20
|
+
end
|
21
|
+
return html.target!
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
data/lib/interview/text.rb
CHANGED
@@ -28,13 +28,13 @@ module Interview
|
|
28
28
|
def render_text(html)
|
29
29
|
if @bold
|
30
30
|
html.b do
|
31
|
-
html.text!
|
31
|
+
html << @text # todo: besser .text! statt << ?
|
32
32
|
@controls.each do |control|
|
33
33
|
html << control.render
|
34
34
|
end
|
35
35
|
end
|
36
36
|
else
|
37
|
-
html
|
37
|
+
html << @text if @text # todo: besser .text! statt << ?
|
38
38
|
@controls.each do |control|
|
39
39
|
html << control.render
|
40
40
|
end
|
data/lib/interview/version.rb
CHANGED
data/lib/interview.rb
CHANGED
@@ -52,9 +52,12 @@ require "interview/form"
|
|
52
52
|
require "interview/nested_form"
|
53
53
|
require "interview/nested_form_remove_link"
|
54
54
|
require "interview/nested_form_add_link"
|
55
|
+
require "interview/nested_form_add_images"
|
55
56
|
require "interview/form_errors"
|
56
57
|
require "interview/polymorphic_add_link"
|
57
58
|
require "interview/search_form"
|
59
|
+
require "interview/button"
|
60
|
+
require "interview/progress_bar"
|
58
61
|
|
59
62
|
require "interview/association_methods"
|
60
63
|
|
@@ -160,60 +163,68 @@ module ActiveRecord
|
|
160
163
|
return [sql] + values
|
161
164
|
end
|
162
165
|
|
163
|
-
def self.string_filter_to_sql(attr, filter,
|
166
|
+
def self.string_filter_to_sql(attr, filter, negation=false)
|
167
|
+
negation = negation ? 'NOT ' : ''
|
164
168
|
if filter.respond_to?(:each)
|
165
|
-
|
169
|
+
return self.value_combination_to_sql(attr, filter, :string)
|
166
170
|
else
|
167
|
-
sql = "#{attr} = ?"
|
171
|
+
sql = "#{negation}#{attr} = ?"
|
168
172
|
end
|
169
173
|
return [sql, filter]
|
170
174
|
end
|
171
175
|
|
172
|
-
def self.number_filter_to_sql(attr, filter,
|
176
|
+
def self.number_filter_to_sql(attr, filter, negation=false)
|
177
|
+
negation = negation ? 'NOT ' : ''
|
173
178
|
if filter.respond_to?(:each)
|
174
179
|
return self.value_combination_to_sql(attr, filter, :number)
|
175
180
|
elsif filter.is_a? String
|
176
181
|
unless result = filter.match(/^([!<>=]*)(\d+\.?\d*)$/)
|
177
182
|
raise "invalid number filter: '#{filter}'"
|
178
183
|
end
|
179
|
-
|
184
|
+
connective = result[1].blank? ? '=' : result[1]
|
180
185
|
value = result[2].include?('.') ? result[2].to_f : result[2].to_i
|
181
|
-
sql = "#{attr} #{
|
186
|
+
sql = "#{negation}#{attr} #{connective} ?"
|
182
187
|
values = [value]
|
183
188
|
else
|
184
|
-
sql = "#{attr} = ?"
|
189
|
+
sql = "#{negation}#{attr} = ?"
|
185
190
|
values = [filter]
|
186
191
|
end
|
187
192
|
return [sql] + values
|
188
193
|
end
|
189
194
|
|
190
|
-
def self.date_filter_to_sql(attr, filter,
|
195
|
+
def self.date_filter_to_sql(attr, filter, negation=false)
|
196
|
+
negation = negation ? 'NOT ' : ''
|
191
197
|
if filter.respond_to?(:each)
|
192
|
-
if filter.size != 2
|
198
|
+
if filter.size != 2 # todo: value_combination einbauen
|
193
199
|
raise "invalid date filter: #{filter.inspect} 2 elements expected, #{filter.size} given"
|
194
200
|
end
|
195
|
-
sql = "#{attr} BETWEEN ? AND ?"
|
201
|
+
sql = "#{negation}#{attr} BETWEEN ? AND ?"
|
196
202
|
values = filter
|
197
203
|
else
|
198
|
-
sql = "#{attr} = ?"
|
204
|
+
sql = "#{negation}#{attr} = ?"
|
199
205
|
values = [filter]
|
200
206
|
end
|
201
207
|
return [sql] + values
|
202
208
|
end
|
203
209
|
|
204
|
-
def self.boolean_filter_to_sql(attr, filter,
|
205
|
-
|
210
|
+
def self.boolean_filter_to_sql(attr, filter, negation=false)
|
211
|
+
if filter.respond_to?(:each)
|
212
|
+
return self.value_combination_to_sql(attr, filter, :boolean)
|
213
|
+
end
|
214
|
+
negation = negation ? 'NOT ' : ''
|
215
|
+
return ["#{negation}#{attr} = ?", filter]
|
206
216
|
end
|
207
217
|
|
208
|
-
def self.assoc_filter_to_sql(attr, filter,
|
218
|
+
def self.assoc_filter_to_sql(attr, filter, negation=false)
|
209
219
|
if filter.respond_to?(:each)
|
210
220
|
return self.value_combination_to_sql(attr, filter, :assoc)
|
211
221
|
end
|
222
|
+
negation = negation ? 'NOT ' : ''
|
212
223
|
assoc = self.reflect_on_association(attr)
|
213
224
|
if assoc.macro == :has_and_belongs_to_many
|
214
225
|
number_filter = self.number_filter_to_sql(assoc.association_foreign_key, filter)
|
215
226
|
values = number_filter[1..-1]
|
216
|
-
sql = "id #{
|
227
|
+
sql = "id #{negation}IN (SELECT #{assoc.foreign_key} FROM #{assoc.join_table} WHERE #{number_filter.first})"
|
217
228
|
end # todo: erweitern
|
218
229
|
return [sql] + values
|
219
230
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: interview
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jannes Köhler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-11-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -126,6 +126,7 @@ files:
|
|
126
126
|
- lib/interview/attribute.rb
|
127
127
|
- lib/interview/boolean_attribute.rb
|
128
128
|
- lib/interview/breadcrumbs.rb
|
129
|
+
- lib/interview/button.rb
|
129
130
|
- lib/interview/collapse_container.rb
|
130
131
|
- lib/interview/condition_container.rb
|
131
132
|
- lib/interview/container_attribute.rb
|
@@ -153,12 +154,14 @@ files:
|
|
153
154
|
- lib/interview/navigation_item.rb
|
154
155
|
- lib/interview/navigation_item_old.rb
|
155
156
|
- lib/interview/nested_form.rb
|
157
|
+
- lib/interview/nested_form_add_images.rb
|
156
158
|
- lib/interview/nested_form_add_link.rb
|
157
159
|
- lib/interview/nested_form_remove_link.rb
|
158
160
|
- lib/interview/object_context.rb
|
159
161
|
- lib/interview/option_attribute.rb
|
160
162
|
- lib/interview/panel.rb
|
161
163
|
- lib/interview/polymorphic_add_link.rb
|
164
|
+
- lib/interview/progress_bar.rb
|
162
165
|
- lib/interview/search_form.rb
|
163
166
|
- lib/interview/space.rb
|
164
167
|
- lib/interview/string_attribute.rb
|