interview 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|