interview 0.0.6 → 0.0.7

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.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/lib/generators/interview/install/install_generator.rb +3 -0
  3. data/lib/generators/interview/install/templates/application.css +14 -0
  4. data/lib/generators/interview/install/templates/application.js +2 -0
  5. data/lib/generators/interview/install/templates/blueimp-gallery.css +226 -0
  6. data/lib/generators/interview/install/templates/blueimp-gallery.js +1341 -0
  7. data/lib/generators/interview/install/templates/bootstrap_interview.css.scss +28 -0
  8. data/lib/generators/interview/install/templates/interview.js.coffee +60 -2
  9. data/lib/generators/interview/install/templates/missing_thumb.png +0 -0
  10. data/lib/interview/association_attribute.rb +6 -8
  11. data/lib/interview/association_list_attribute.rb +3 -2
  12. data/lib/interview/attribute.rb +52 -30
  13. data/lib/interview/collapse_container.rb +20 -0
  14. data/lib/interview/condition_container.rb +19 -0
  15. data/lib/interview/dropdown.rb +16 -4
  16. data/lib/interview/form.rb +42 -47
  17. data/lib/interview/form_errors.rb +2 -2
  18. data/lib/interview/grid.rb +1 -1
  19. data/lib/interview/image_attribute.rb +55 -15
  20. data/lib/interview/image_gallery_attribute.rb +74 -0
  21. data/lib/interview/image_light_box.rb +19 -0
  22. data/lib/interview/link.rb +2 -1
  23. data/lib/interview/list.rb +8 -2
  24. data/lib/interview/media_object.rb +45 -0
  25. data/lib/interview/navigation_item.rb +19 -4
  26. data/lib/interview/navigation_item_old.rb +26 -0
  27. data/lib/interview/nested_form_add_link.rb +1 -1
  28. data/lib/interview/panel.rb +18 -0
  29. data/lib/interview/polymorphic_add_link.rb +33 -4
  30. data/lib/interview/search_form.rb +21 -0
  31. data/lib/interview/text.rb +33 -3
  32. data/lib/interview/version.rb +1 -1
  33. data/lib/interview/view.rb +28 -6
  34. data/lib/interview.rb +12 -0
  35. metadata +13 -2
@@ -4,6 +4,11 @@
4
4
 
5
5
  $navbar-default-brand-color: $brand-primary;
6
6
  $navbar-default-bg: $brand-primary-lighten;
7
+ $navbar-inverse-brand-color: $brand-primary-lighten;
8
+ $navbar-inverse-bg: $brand-primary;
9
+ $navbar-inverse-color: #ffffff;
10
+ $navbar-inverse-link-color: $brand-primary-lighten;
11
+ $navbar-inverse-link-hover-color: #ffffff;
7
12
 
8
13
  @import 'bootstrap';
9
14
 
@@ -95,4 +100,27 @@ $nav-stacked-link-padding-level2: 5px 15px 5px 45px !default;
95
100
  input {
96
101
  width: auto;
97
102
  }
103
+ }
104
+
105
+ .inline-block {
106
+ display: inline-block;
107
+ /* IE 7 hack */
108
+ *zoom:1;
109
+ *display: inline;
110
+ vertical-align: middle;
111
+ margin-right: 10px;
112
+ }
113
+
114
+ .list-item {
115
+ margin-top: 15px;
116
+ }
117
+
118
+ .img-thumb {
119
+ display: inline-block;
120
+ /* IE 7 hack */
121
+ *zoom:1;
122
+ *display: inline;
123
+ vertical-align: middle;
124
+ margin-right: 5px;
125
+ margin-bottom: 5px;
98
126
  }
@@ -42,7 +42,7 @@ jQuery ->
42
42
  e.preventDefault()
43
43
  object_class = $('#add_link_class').children('option:selected').val()
44
44
  if object_class != ''
45
- location.href = "#{$(this).attr('href')}?type=#{object_class}"
45
+ location.href = "#{$(this).attr('href')}?filter%5Btype%5D=#{object_class}"
46
46
 
47
47
  $('.jstree').each ->
48
48
  params =
@@ -69,4 +69,62 @@ jQuery ->
69
69
  "position": data.position
70
70
  error: (data) ->
71
71
  tree.jstree('refresh')
72
- $(tree).before("<div class=\"alert alert-danger\">#{data.responseText}</div>")
72
+ $(tree).before("<div class=\"alert alert-danger\">#{data.responseText}</div>")
73
+
74
+ $('.collapse_link').click (e) ->
75
+ e.preventDefault()
76
+ $($(this).data('target')).collapse('toggle')
77
+
78
+ $('.img-link').click (e) ->
79
+ links = $('.img-link')
80
+ target = event.target || event.srcElement
81
+ link = if target.src then target.parentNode else target
82
+ options = { index: link, event: e }
83
+ blueimp.Gallery(links, options)
84
+
85
+ $('.image-upload').fileupload
86
+ add: (e, data) ->
87
+ types = /(\.|\/)(gif|jpe?g|png|mov|mpeg|mpeg4|avi)$/i
88
+ file = data.files[0]
89
+ if types.test(file.type) || types.test(file.name)
90
+ data.context = $(tmpl("upload-progress-script", file))
91
+ $('#upload-progress').append($(data.context))
92
+
93
+ $("input[name='_method']").attr('name', 'method')
94
+ data.submit()
95
+ $("input[name='method']").attr('name', '_method')
96
+ else
97
+ alert("#{file.name} is not a gif, jpg or png image file")
98
+ progress: (e, data) ->
99
+ if data.context
100
+ progress = parseInt(data.loaded / data.total * 100, 10)
101
+ data.context.find('.bar').css('width', progress + '%')
102
+ done: (e, data) ->
103
+ $('#image-tag').attr('src', data.result.thumb_url)
104
+ # context = $(tmpl("image-thumb-script", data.result))
105
+ # $('#image-gallery').append($(context))
106
+ $('.image-id').attr('value', data.result.id)
107
+
108
+ $('.multiple-image-upload').fileupload
109
+ add: (e, data) ->
110
+ types = /(\.|\/)(gif|jpe?g|png|mov|mpeg|mpeg4|avi)$/i
111
+ file = data.files[0]
112
+ if types.test(file.type) || types.test(file.name)
113
+ data.context = $(tmpl("upload-progress-script", file))
114
+ $('#upload-progress').append($(data.context))
115
+
116
+ $("input[name='_method']").attr('name', 'method')
117
+ data.submit()
118
+ $("input[name='method']").attr('name', '_method')
119
+ else
120
+ alert("#{file.name} is not a gif, jpg or png image file")
121
+ progress: (e, data) ->
122
+ if data.context
123
+ progress = parseInt(data.loaded / data.total * 100, 10)
124
+ data.context.find('.bar').css('width', progress + '%')
125
+ done: (e, data) ->
126
+ context = $(tmpl("image-thumb-script", data.result))
127
+ $('#image-gallery').append($(context))
128
+ ids = JSON.parse($('.image-ids').attr('value'))
129
+ ids.push data.result.id
130
+ $('.image-ids').attr('value', JSON.stringify(ids))
@@ -6,13 +6,10 @@ module Interview
6
6
  def render_read
7
7
  return '' if value.nil?
8
8
  assoc_object = value
9
- if h.respond_to? "#{@method}_path"
10
- return Link.new(parent: self,
11
- caption: "#{assoc_object.human_id}",
12
- object: assoc_object).render
13
- else
14
- return assoc_object.human_id
15
- end
9
+ # todo: Link nicht anzeigen, wenn Route für Objekt nicht existiert
10
+ return Link.new(parent: self,
11
+ caption: "#{assoc_object.human_id}",
12
+ object: assoc_object).render
16
13
  end
17
14
 
18
15
  def render_write
@@ -26,7 +23,8 @@ module Interview
26
23
  assoc_class = object.class.new.send("build_#{@method}").class
27
24
  pool = assoc_class.all
28
25
  end
29
- form_builder.collection_select "#{@method}_id", pool, :id, :human_id, {prompt: true}, {class: 'form-control'}
26
+ form_builder.collection_select "#{@method}_id", pool, :id, :human_id, {include_blank: true}, {class: 'form-control'}
27
+ # todo: prompt einbauen
30
28
  end
31
29
 
32
30
  end
@@ -1,7 +1,7 @@
1
1
  module Interview
2
2
  class AssociationListAttribute < Attribute
3
3
 
4
- attr_accessor :use
4
+ attr_accessor :use, :size
5
5
 
6
6
  def render_read
7
7
  return '' if value.nil?
@@ -17,6 +17,7 @@ module Interview
17
17
  end
18
18
 
19
19
  def render_write
20
+ size = @size || 8
20
21
  if @use == 'multi_select'
21
22
  object = find_attribute!(:object)
22
23
  if object.respond_to? "#{method.singularize}_pool"
@@ -25,7 +26,7 @@ module Interview
25
26
  assoc_class = object.class.new.send(@method).build.class
26
27
  pool = assoc_class.all
27
28
  end
28
- form_builder.collection_select "#{@method.singularize}_ids", pool, :id, :human_id, {prompt: true}, {class: 'form-control', multiple: true}
29
+ form_builder.collection_select "#{@method.singularize}_ids", pool, :id, :human_id, {prompt: true}, {class: 'form-control', multiple: true, size: size}
29
30
  # form_builder.collection_select "#{@method.singularize}_ids", Category.all.collect {|x| [x.name, x.id]}, {}, :multiple => true
30
31
  else
31
32
  return form_builder.text_field "#{@method}_human_ids_string", class: 'form-control'
@@ -2,10 +2,15 @@ module Interview
2
2
  class Attribute < Control
3
3
 
4
4
  attr_accessor :method, :caption, :style, :link, :nil_value, :hide_caption, :hide_tooltip,
5
- :only_for, :align, :on_changed
5
+ :only_for, :align, :on_changed, :html_class, :surrounding_tag
6
+
7
+ def initialize(params={})
8
+ @html_class = []
9
+ super
10
+ end
6
11
 
7
12
  def value
8
- object = find_attribute! :object
13
+ object = @object || find_attribute!(:object)
9
14
  if object.respond_to? @method
10
15
  val = object.send @method
11
16
  end
@@ -18,14 +23,13 @@ module Interview
18
23
  return @caption
19
24
  else
20
25
  object = find_attribute! :object
21
- puts "#{object.class.name} #{@method}"
22
26
  return object.class.human_attribute_name(@method)
23
27
  end
24
28
  end
25
29
 
26
30
  def tooltip
27
31
  object = find_attribute! :object
28
- return h.t("activerecord.tooltips.#{object.class.name.underscore}.attributes.#{@method}", default: '')
32
+ return h.t("activerecord.attribute_tooltips.#{object.class.model_name.i18n_key}.#{@method}", default: '')
29
33
  end
30
34
 
31
35
 
@@ -33,10 +37,11 @@ module Interview
33
37
  return '' if hide?
34
38
 
35
39
  if @style and respond_to?("render_#{@style}_style", true)
36
- return send("render_#{@style}_style")
40
+ html = send("render_#{@style}_style")
37
41
  else
38
- return render_default_style
42
+ html = render_default_style
39
43
  end
44
+ return add_surrounding_tag(html)
40
45
  end
41
46
 
42
47
  def render_read
@@ -74,45 +79,62 @@ module Interview
74
79
  object = find_attribute! :object
75
80
  align = @align || find_attribute(:align)
76
81
 
77
- html = Builder::XmlMarkup.new
78
- html.div class: "form-group" do # todo: old class: "form-group attribute_#{@method.to_s} collapse in"
79
- opts = {}
80
- opts[:class] = 'col-xs-3 control-label' if align == 'horizontal'
81
- opts[:class] = 'sr-only' if align == 'inline'
82
- if @hide_caption
83
- html.div opts
84
- else
85
- html << form_builder.label(@method, opts) do
86
- form_html = Builder::XmlMarkup.new
87
- form_html.text! caption
88
- # if not @hide_tooltip and tooltip != ''
89
- # form_html.text! ' '
90
- # form_html << Tooltip.new(tooltip: tooltip, style: :popover).render
91
- # end
92
- form_html.target!.html_safe
93
- end
94
- end
82
+ html = Builder::XmlMarkup.new(indent: 2)
83
+ html.div class: 'form-group' do
84
+
85
+ html.div class: 'col-xs-3' if @hide_caption and align == 'horizontal'
86
+ render_form_label(html)
87
+
95
88
  if align == 'horizontal'
96
89
  html.div class: 'col-xs-9' do
97
90
  html << render_write
98
- if not @hide_tooltip and tooltip != ''
99
- html.p tooltip, class: 'help-block'
100
- end
91
+ render_form_tooltip(html)
101
92
  end
102
93
  else
103
94
  html << render_write
104
- if not @hide_tooltip and tooltip != ''
105
- html.p tooltip, class: 'help-block'
106
- end
95
+ render_form_tooltip(html)
107
96
  end
97
+
108
98
  end
109
99
  return html.target!
110
100
  end
111
101
 
102
+ def render_form_label(html)
103
+ align = @align || find_attribute(:align)
104
+ html_opts = if @hide_caption or align == 'inline'
105
+ { class: 'sr-only' }
106
+ elsif align == 'horizontal'
107
+ { class: 'col-xs-3 control-label' }
108
+ else
109
+ {}
110
+ end
111
+ html << form_builder.label(@method, html_opts) do
112
+ form_html = Builder::XmlMarkup.new
113
+ form_html.text! caption
114
+ form_html.target!.html_safe
115
+ end
116
+ end
117
+
118
+ def render_form_tooltip(html)
119
+ if not @hide_tooltip and tooltip != ''
120
+ html.p tooltip, class: 'help-block'
121
+ end
122
+ end
123
+
112
124
  def form_builder
113
125
  return find_attribute! :form_builder
114
126
  end
115
127
 
128
+ def add_surrounding_tag(html)
129
+ if @surrounding_tag
130
+ opts = {}
131
+ opts[:class] = @html_class.join(' ') unless @html_class.empty?
132
+ return h.content_tag @surrounding_tag.to_sym, html, opts
133
+ else
134
+ return html
135
+ end
136
+ end
137
+
116
138
  def add_link(value)
117
139
  if @link
118
140
  return Link.new(parent: @parent, caption: value.to_s).render
@@ -0,0 +1,20 @@
1
+ module Interview
2
+ class CollapseContainer < Control
3
+ include HasControls
4
+
5
+ attr_accessor :caption
6
+
7
+ def render
8
+ html = Builder::XmlMarkup.new
9
+ new_id = Time.now.to_f.to_s.delete('.')
10
+ html << h.link_to(@caption, '#', class: 'collapse_link', data: { toggle: 'collapse', target: "##{new_id}" })
11
+ html.div id: new_id, class: 'panel-collapse collapse' do
12
+ @controls.each do |control|
13
+ html << control.render
14
+ end
15
+ end
16
+ return html.target!
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module Interview
2
+ class ConditionContainer < Control
3
+ include HasControls
4
+
5
+ attr_accessor :condition
6
+
7
+ def render
8
+ object = find_attribute :object
9
+ if @condition.call(object)
10
+ return @controls.map do |control|
11
+ control.render
12
+ end.join
13
+ else
14
+ return ''
15
+ end
16
+ end
17
+
18
+ end
19
+ end
@@ -2,13 +2,25 @@ module Interview
2
2
  class Dropdown < Control
3
3
  include HasControls
4
4
 
5
- attr_accessor :caption, :align
5
+ attr_accessor :image, :caption, :style, :html_class
6
+
7
+ def initialize(params={})
8
+ @html_class = []
9
+ super
10
+ end
6
11
 
7
12
  def render
8
13
  html = Builder::XmlMarkup.new
9
- html.div class: 'dropdown' do
10
- html.a class: 'dropdown-toggle btn btn-default', href: '#', :'data-toggle' => 'dropdown' do
11
- html.text! @caption + ' '
14
+ html_class = @html_class.dup
15
+ html_class << 'dropdown'
16
+ html.div class: html_class.join(' ') do
17
+ html_class = 'dropdown-toggle'
18
+ html_class += ' btn btn-default' if @style == 'button'
19
+ html.a class: html_class, href: '#', :'data-toggle' => 'dropdown' do
20
+ html.span '', class: "glyphicon glyphicon-#{@image}" if @image
21
+ html.text! ' ' if @image and @caption
22
+ html.text! @caption if @caption
23
+ html.text! ' ' if @caption
12
24
  html.span '', class: 'caret'
13
25
  end
14
26
  html.ul class: 'dropdown-menu' do
@@ -5,64 +5,59 @@ module Interview
5
5
  attr_accessor :skip_submit, :multi_create, :align, :redirect_to
6
6
  attr_reader :form_builder
7
7
 
8
- def attribute_modus
9
- return :write
10
- end
11
-
12
- def render # todo: Aufräumen
8
+ def render
13
9
  object = find_attribute!(:object)
14
- model = object.class.lookup_ancestors.last.model_name.singular # todo
15
- # if object.class.superclass.name == 'ActiveRecord::Base'
16
- # model = object.class.name.underscore
17
- # else
18
- # model = object.class.superclass.name.underscore
19
- # end
20
- if object.id
21
- url = h.send("#{model}_path", object)
22
- else
23
- url = h.send("#{model.pluralize}_path")
10
+ html_options = case @align
11
+ when 'horizontal' then { class: 'form-horizontal' }
12
+ when 'inline' then { class: 'form-inline' }
13
+ else {}
24
14
  end
25
- opts = {as: model.to_sym, url: url, role: 'form', html: {}}
26
- opts[:html][:class] = 'form-horizontal' if @align == 'horizontal'
27
- opts[:html][:class] = 'form-inline' if @align == 'inline'
28
- html = Builder::XmlMarkup.new
29
- html << h.form_for(object, opts) do |form_builder|
15
+ return h.form_for(object, role: 'form', html: html_options) do |form_builder|
30
16
  @form_builder = form_builder
31
- form_html = Builder::XmlMarkup.new
32
- form_html << FormErrors.new(parent: self).render
33
- if @redirect_to == :parent and Object.const_defined? 'Gretel'
34
- form_html << h.hidden_field_tag('redirect_to', h.parent_breadcrumb.url)
35
- end
17
+ html = Builder::XmlMarkup.new(indent: 2)
18
+
19
+ render_default_controls(html)
36
20
 
37
21
  @controls.each do |control|
38
- form_html << control.render
39
- form_html.text! ' ' if @align == 'inline'
22
+ html << control.render
23
+ html.text! ' ' if @align == 'inline'
40
24
  end
41
25
 
42
- if not @skip_submit
43
- if @align == 'horizontal'
44
- form_html.div class: 'form-group' do
45
- form_html.div class: 'col-sm-offset-3 col-sm-9' do
46
- form_html << form_builder.submit(class: 'btn btn-primary')
47
- if @multi_create || find_attribute(:multi_create)
48
- form_html.text! ' '
49
- form_html << h.check_box_tag('new_record', '1', true)
50
- form_html.text! ' und weiteren Datesatz'
51
- end
52
- end
53
- end
54
- else
55
- form_html << form_builder.submit(class: 'btn btn-primary')
56
- if @multi_create || find_attribute(:multi_create)
57
- form_html.text! ' '
58
- form_html << h.check_box_tag('new_record', '1', true)
59
- form_html.text! ' und weiteren Datesatz'
26
+ if @align == 'horizontal'
27
+ html.div class: 'form-group' do
28
+ html.div class: 'col-sm-offset-3 col-sm-9' do
29
+ render_submit(html)
60
30
  end
61
31
  end
32
+ else
33
+ render_submit(html)
34
+ end
35
+
36
+ html.target!.html_safe
37
+ end
38
+ end
39
+
40
+ protected
41
+
42
+ def render_submit(html)
43
+ if not @skip_submit
44
+ html << form_builder.submit(class: 'btn btn-primary')
45
+ if @multi_create || find_attribute(:multi_create)
46
+ html.text! ' '
47
+ html << h.check_box_tag('new_record', '1', true)
48
+ html.text! ' und weiteren Datesatz' # todo
62
49
  end
63
- form_html.target!.html_safe
64
50
  end
65
- return html.target!
51
+ end
52
+
53
+ def render_default_controls(html)
54
+ html << FormErrors.new(parent: self).render
55
+
56
+ if @redirect_to == :parent and Object.const_defined? 'Gretel'
57
+ html << h.hidden_field_tag('redirect_to', h.parent_breadcrumb.url)
58
+ elsif @redirect_to == :current
59
+ html << h.hidden_field_tag('redirect_to', h.request.original_url)
60
+ end
66
61
  end
67
62
 
68
63
  end
@@ -6,8 +6,8 @@ module Interview
6
6
 
7
7
  html = Builder::XmlMarkup.new
8
8
  if object.errors.any?
9
- html.div class: 'error_explanation!' do
10
- html.h2 "#{pluralize(object.errors.count, 'error')} prohibited this article from being saved:"
9
+ html.div class: 'alert alert-danger' do
10
+ html.h4 h.translate("errors.template.header", count: object.errors.count, model: object.class.model_name.human)
11
11
  html.ul do
12
12
  object.errors.full_messages.each do |msg|
13
13
  html.li msg
@@ -44,7 +44,7 @@ module Interview
44
44
  end
45
45
  end
46
46
  if objects.empty?
47
- html.p "Keine #{@object.class.model_name.human(count: 2)} vorhanden.", class: 'text-center text-muted'
47
+ html.p "Keine #{@object.class.human_name(count: 2)} vorhanden.", class: 'text-center text-muted'
48
48
  end
49
49
  return html.target!
50
50
  end
@@ -1,32 +1,72 @@
1
1
  module Interview
2
2
  class ImageAttribute < Attribute
3
3
 
4
- attr_accessor :image_style, :hide_if_not_exists
4
+ # - Bild muss in eingener Klasse ausgelagert werden
5
+ # - object muss die Methode method_id= implementieren
6
+ # - method_id muss als parameter erlaubt werden
7
+ # - json ansicht auf bild muss vorhanden sein
8
+
9
+ attr_accessor :object, :submethod, :image_style, :hide_if_not_exists
5
10
 
6
11
  def render_read
7
- return '' if value.nil?
12
+ submethod = @submethod || 'attachment'
8
13
  image_style = @image_style || :thumb
9
- if not value.exists? and @hide_if_not_exists
10
- return ''
11
- else
12
- return h.image_tag value.url(image_style)
14
+ object = @object || find_attribute(:object)
15
+ image = value || object.association(@method).build
16
+
17
+ attachment = image.send(submethod)
18
+ return '' if not attachment.exists? and @hide_if_not_exists
19
+
20
+ html = Builder::XmlMarkup.new
21
+ opts = {class: "image_#{image_style}"}
22
+ opts[:class] += ' ' + @html_class.join(' ') unless @html_class.empty? or @surrounding_tag
23
+ html.div opts do
24
+ html << h.image_tag(attachment.url(image_style), class: 'img-responsive')
13
25
  end
26
+ return html.target!
14
27
  end
15
28
 
16
29
  def render_write
17
- object = find_attribute(:object)
18
- image = object.send @method
30
+ object = @object || find_attribute(:object)
31
+ submethod = @submethod || 'attachment'
32
+ 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
19
36
 
20
37
  html = Builder::XmlMarkup.new
21
- if image.exists? and @image_style
22
- html.br
23
- html << h.image_tag(image.url(@image_style))
38
+
39
+ html << form_builder.hidden_field("#{@method.singularize}_id", class: 'image-id')
40
+
41
+ html.div class: 'inline-block' do
42
+ html << h.image_tag(attachment.url(image_style), id: 'image-tag')
24
43
  end
25
- html << form_builder.file_field(@method)
26
- if image.exists?
27
- html << form_builder.check_box("destroy_#{@method}")
28
- html.text! ' Datei löschen'
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'})
50
+ end
51
+
52
+ # if attachment.exists?
53
+ # html << form_builder.check_box("destroy_#{@method}")
54
+ # html.text! ' Datei löschen'
55
+ # end
56
+ end
57
+
58
+ html.div id: 'upload-progress' do
29
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%'
66
+ end
67
+ end
68
+ end
69
+
30
70
  return html.target!
31
71
  end
32
72
 
@@ -0,0 +1,74 @@
1
+ module Interview
2
+ class ImageGalleryAttribute < Attribute
3
+
4
+ attr_accessor :object, :submethod, :image_style, :light_box_image_style
5
+
6
+ def render_read
7
+ submethod = @submethod || 'attachment'
8
+ image_style = @image_style || :thumb
9
+ images = value
10
+
11
+ html = Builder::XmlMarkup.new
12
+ render_gallery(html, images, submethod, image_style, @light_box_image_style)
13
+ return html.target!
14
+ end
15
+
16
+ def render_write
17
+ object = @object || find_attribute(:object)
18
+ submethod = @submethod || 'attachment'
19
+ image_style = @image_style || :thumb
20
+ images = object.send @method
21
+ model = images.klass.model_name.singular
22
+
23
+ html = Builder::XmlMarkup.new
24
+ html.div class: 'image-upload-group' do
25
+
26
+ html << form_builder.hidden_field("#{@method.singularize}_ids", class: 'image-ids')
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
+ 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
+
37
+ html.div class: "clearfix" do
38
+ html.span class: "btn btn-default fileinput-button" do
39
+ html.span "Bilder hinzufügen" # todo
40
+ html << h.file_field_tag("#{model}[#{submethod}]", class: 'multiple-image-upload', multiple: true,
41
+ data: {url: "/#{model.pluralize}.json", type: 'POST'})
42
+ end
43
+ end
44
+
45
+ html.div class: 'upload-progress' do
46
+ end
47
+
48
+ html.script id: 'upload-progress-script', type: 'text/x-tmpl' do
49
+ html.div class: 'upload' do
50
+ html.text! "{%=o.name%}"
51
+ html.div class: 'progress' do
52
+ html.div '', class: 'progress-bar bar', style: 'width: 0%'
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ return html.target!
59
+ end
60
+
61
+ protected
62
+
63
+ def render_gallery(html, images, submethod, image_style, light_box_image_style)
64
+ html.div class: 'image-gallery' do
65
+ images.each do |image|
66
+ html.a href: image.send(submethod).url(light_box_image_style), class: 'img-link' do
67
+ html << h.image_tag(image.send(submethod).url(image_style), class: 'img-thumb')
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ end
74
+ end