spyro 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +3 -0
  4. data/Rakefile +37 -0
  5. data/app/assets/OLDjavascripts/application.js +25 -0
  6. data/app/assets/OLDjavascripts/components.es6 +10 -0
  7. data/app/assets/OLDjavascripts/components/base/base.es6 +197 -0
  8. data/app/assets/OLDjavascripts/components/base/collection.es6 +199 -0
  9. data/app/assets/OLDjavascripts/components/base/element.es6 +134 -0
  10. data/app/assets/OLDjavascripts/components/base/field.es6 +26 -0
  11. data/app/assets/OLDjavascripts/components/base/inputs/text.es6 +21 -0
  12. data/app/assets/OLDjavascripts/components/base/pagination.es6 +23 -0
  13. data/app/assets/OLDjavascripts/vendor/lodash.js +121 -0
  14. data/app/assets/OLDjavascripts/vendor/moment-twitter.js +86 -0
  15. data/app/assets/OLDjavascripts/vendor/moment.js +80 -0
  16. data/app/assets/OLDjavascripts/vendor/pluralize.js +433 -0
  17. data/app/views/base/_associations.html.haml +11 -0
  18. data/app/views/base/_custom.html.haml +0 -0
  19. data/app/views/base/_details.html.haml +3 -0
  20. data/app/views/base/_edit_header.html.haml +3 -0
  21. data/app/views/base/_fields.html.haml +11 -0
  22. data/app/views/base/_form.html.haml +6 -0
  23. data/app/views/base/_index_header.html.haml +4 -0
  24. data/app/views/base/_new_header.html.haml +3 -0
  25. data/app/views/base/_other_form_fields.html.haml +0 -0
  26. data/app/views/base/_show_header.html.haml +9 -0
  27. data/app/views/base/_upload_fields.html.haml +5 -0
  28. data/app/views/base/copy.html.haml +10 -0
  29. data/app/views/base/edit.html.haml +4 -0
  30. data/app/views/base/index.csv.haml +8 -0
  31. data/app/views/base/index.html.haml +7 -0
  32. data/app/views/base/index.js.haml +2 -0
  33. data/app/views/base/index.xls.ruby +12 -0
  34. data/app/views/base/mailer.html.haml +46 -0
  35. data/app/views/base/new.html.haml +4 -0
  36. data/app/views/base/notify.html.haml +11 -0
  37. data/app/views/base/show.html.haml +8 -0
  38. data/app/views/base/stats.html.haml +36 -0
  39. data/app/views/base/trombi.html.haml +1 -0
  40. data/app/views/base/upload.html.haml +24 -0
  41. data/config/initializers/assets.rb +1 -0
  42. data/config/routes.rb +2 -0
  43. data/lib/spyro.rb +24 -0
  44. data/lib/spyro/active_record_add_on.rb +38 -0
  45. data/lib/spyro/application_controller_add_on.rb +24 -0
  46. data/lib/spyro/collections/outputs/admin_table.rb +28 -0
  47. data/lib/spyro/collections/outputs/bar_graph_table.rb +46 -0
  48. data/lib/spyro/collections/outputs/base.rb +23 -0
  49. data/lib/spyro/collections/outputs/csv.rb +34 -0
  50. data/lib/spyro/collections/outputs/fields.rb +118 -0
  51. data/lib/spyro/collections/outputs/flatui_table.rb +40 -0
  52. data/lib/spyro/collections/outputs/inplace_table.rb +29 -0
  53. data/lib/spyro/collections/outputs/map.rb +22 -0
  54. data/lib/spyro/collections/outputs/table.rb +126 -0
  55. data/lib/spyro/collections/outputs/xlsx.rb +39 -0
  56. data/lib/spyro/collections/parsers/active_ldap_relation.rb +22 -0
  57. data/lib/spyro/collections/parsers/active_record_relation.rb +138 -0
  58. data/lib/spyro/collections/parsers/array.rb +38 -0
  59. data/lib/spyro/collections/parsers/base.rb +60 -0
  60. data/lib/spyro/collections/parsers/kaminari_array.rb +38 -0
  61. data/lib/spyro/collections/parsers/model.rb +31 -0
  62. data/lib/spyro/controllers/strong_parameted.rb +33 -0
  63. data/lib/spyro/engine.rb +6 -0
  64. data/lib/spyro/filters_controller_add_on.rb +161 -0
  65. data/lib/spyro/helpers/action_view_extension.rb +726 -0
  66. data/lib/spyro/namespace_template_inheritance.rb +30 -0
  67. data/lib/spyro/usefull_attributes.rb +14 -0
  68. data/lib/spyro/version.rb +3 -0
  69. data/lib/tasks/spyro_tasks.rake +4 -0
  70. data/test/dummy/README.rdoc +28 -0
  71. data/test/dummy/Rakefile +6 -0
  72. data/test/dummy/app/assets/javascripts/application.js +13 -0
  73. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  74. data/test/dummy/app/controllers/application_controller.rb +5 -0
  75. data/test/dummy/app/helpers/application_helper.rb +2 -0
  76. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  77. data/test/dummy/bin/bundle +3 -0
  78. data/test/dummy/bin/rails +4 -0
  79. data/test/dummy/bin/rake +4 -0
  80. data/test/dummy/bin/setup +29 -0
  81. data/test/dummy/config.ru +4 -0
  82. data/test/dummy/config/application.rb +26 -0
  83. data/test/dummy/config/boot.rb +5 -0
  84. data/test/dummy/config/database.yml +25 -0
  85. data/test/dummy/config/environment.rb +5 -0
  86. data/test/dummy/config/environments/development.rb +41 -0
  87. data/test/dummy/config/environments/production.rb +79 -0
  88. data/test/dummy/config/environments/test.rb +42 -0
  89. data/test/dummy/config/initializers/assets.rb +11 -0
  90. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  91. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  92. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  93. data/test/dummy/config/initializers/inflections.rb +16 -0
  94. data/test/dummy/config/initializers/mime_types.rb +4 -0
  95. data/test/dummy/config/initializers/session_store.rb +3 -0
  96. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  97. data/test/dummy/config/locales/en.yml +23 -0
  98. data/test/dummy/config/routes.rb +4 -0
  99. data/test/dummy/config/secrets.yml +22 -0
  100. data/test/dummy/public/404.html +67 -0
  101. data/test/dummy/public/422.html +67 -0
  102. data/test/dummy/public/500.html +66 -0
  103. data/test/dummy/public/favicon.ico +0 -0
  104. data/test/integration/navigation_test.rb +8 -0
  105. data/test/spyro_test.rb +7 -0
  106. data/test/test_helper.rb +21 -0
  107. metadata +256 -0
@@ -0,0 +1,34 @@
1
+ require_relative "base"
2
+ require "csv"
3
+
4
+
5
+ module Spyro
6
+ module ActionViewExtension
7
+
8
+ module CollectionForHelper
9
+ module Output
10
+ class CSV < Output::Base
11
+
12
+ def render_header csv
13
+ return unless @unicollection.meta[:data]
14
+ csv << @unicollection.meta[:data]
15
+ end
16
+
17
+ def render_body csv
18
+ @unicollection.rows.each do |row|
19
+ csv << row[:data].map(&:value)
20
+ end
21
+ end
22
+
23
+ def render
24
+ return "" if @unicollection.rows.empty?
25
+ ::CSV.generate({}) do |csv|
26
+ render_header csv
27
+ render_body csv
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,118 @@
1
+
2
+
3
+ module Spyro
4
+ module ActionViewExtension
5
+
6
+ module CollectionForHelper
7
+ module Output
8
+ module Fields
9
+ # Key => [class => object class ; symbol => db_type, string for pattern matching]
10
+ @@fields = { [ActiveSupport::TimeWithZone, ""] => {:method => :datetime},
11
+ [Object, /_prct$/] => {:method => :prct},
12
+ [Float, ""] => {:method => :float},
13
+ [:boolean, ""] => {:method => :boolean},
14
+ [:text, /_html$/] => {:method => :html},
15
+ [:text, /code$/] => {:method => :html},
16
+ [:text, ""] => {:method => :text},
17
+ [String, /_url$/] => {:method => :url},
18
+ #[String, /_email$/] => {:method => :email},
19
+ [String, ""] => {:method => :string}, }
20
+
21
+ @@fields[[CarrierWave::Uploader::Base, /_image$/]] = {:method => :cw_image} if defined? CarrierWave and defined? CarrierWave::Uploader and defined? CarrierWave::Uploader::Base
22
+ @@fields[[CarrierWave::Uploader::Base, ""]] = {:method => :cw_file} if defined? CarrierWave and defined? CarrierWave::Uploader and defined? CarrierWave::Uploader::Base
23
+ @@fields[[ClassyEnum::Base, ""]] = {:method => :classy_enum} if defined? ClassyEnum
24
+
25
+ @@fields[[Object, ""]] = {:method => :default}
26
+
27
+ delegate :l, :link_to, :mail_to, :cw_image_tag, :truncate, :strip_tags, :progress, to: :@h
28
+
29
+ def format_default value, options
30
+ value.to_s
31
+ end
32
+
33
+ def format_classy_enum value, options
34
+ value.blank? ? "" : value.text
35
+ end
36
+
37
+ def format_datetime value, options
38
+ l(value, :format => options[:format] || :datetime)
39
+ end
40
+
41
+ def format_cw_image value, options
42
+ cw_image_tag value, options[:version]
43
+ end
44
+
45
+ def format_cw_file value, options
46
+ link_to value.file.filename, value.url unless value.file.nil?
47
+ end
48
+
49
+ def format_email value, options
50
+ mail_to value
51
+ end
52
+
53
+ def format_boolean value, options
54
+ value ? "Yes" : "No"
55
+ end
56
+
57
+ def format_period values, options
58
+ begin_at, end_at, current = *values
59
+ current ||= Time.zone.now
60
+
61
+ total, actual = (end_at.to_i - begin_at.to_i), (current.to_i - begin_at.to_i)
62
+ current_percentage = [0, 100, (actual * 100) / total].sort.second
63
+ <<EOP
64
+ <div class="col-md-12">
65
+ <span class="date-before col-md-6 pull-left">#{l(begin_at, :format => options[:format] || :datetime)}</span>
66
+ <span class="date-after col-md-6 pull-right">#{l(end_at, :format => options[:format] || :datetime)}</span>
67
+ <div class="col-md-10 col-md-offset-1">
68
+ #{progress current_percentage}
69
+ </div>
70
+ </div>
71
+ EOP
72
+
73
+ end
74
+
75
+ def format_progress values, options
76
+ actual, total = *values
77
+ current_percentage = [0, 100, (actual * 100) / total].sort.second rescue 0
78
+ <<EOP
79
+ <div class="col-md-12">
80
+ <div class="col-md-12 percentage-label">
81
+ #{actual} / #{total}
82
+ </div>
83
+ <div class="col-md-10 col-md-offset-1">
84
+ #{progress current_percentage}
85
+ </div>
86
+ </div>
87
+ EOP
88
+
89
+ end
90
+
91
+ def format_prct value, options
92
+ value ? ("%.2f%%" % value) : "N/A"
93
+ end
94
+
95
+ def format_float value, options
96
+ value ? ("%.2f" % value) : "N/A"
97
+ end
98
+
99
+ def format_url value, options
100
+ link_to value, (value.start_with?('http') ? value : ('http://' + value))
101
+ end
102
+
103
+ def format_html value, options
104
+ "<span class='has-popover' data-html='true' data-content='#{@h.send(:h, value.to_s)}'>#{@h.truncate(@h.strip_tags(HTMLEntities.new.decode(value.to_s)), :length => 40, :separator => ' ')}</span>".html_safe
105
+ end
106
+
107
+ def format_text value, options
108
+ "<span class='has-popover' data-content='#{@h.send(:h, value.to_s)}'>#{@h.truncate(value.to_s, :length => 40, :separator => ' ')}</span>".html_safe
109
+ end
110
+
111
+ def format_string value, options
112
+ value.to_s
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,40 @@
1
+ require_relative "table"
2
+
3
+ module Spyro
4
+ module ActionViewExtension
5
+ module CollectionForHelper
6
+ module Output
7
+ class FlatuiTable < Table
8
+ delegate :link_to, :button, :button_success, :button_danger, :button_info, to: :@h
9
+
10
+ def initialize unicollection, helper, parser_class
11
+ super
12
+ end
13
+
14
+ def render_cell_buttons row
15
+ row[:meta][:actions] = {} if row[:meta][:actions].nil?
16
+
17
+ html = if row[:meta][:actions].is_a? Hash
18
+ row[:meta][:actions].map do |name, link|
19
+ case name
20
+ when :show
21
+ button_success "", link, :icon => :search, :class => 'btn btn-lg'
22
+ when :edit
23
+ button_info "", link, :icon => :edit, :class => "btn btn-lg"
24
+ when :destroy
25
+ button_danger "", link, default_destroy_link_attributes.merge(:icon => :trash, :class => "btn btn-lg")
26
+ else
27
+ button "", link, :icon => :name, :class => "btn btn-lg"
28
+ end
29
+ end.join ''
30
+ else
31
+ row[:meta][:actions]
32
+ end
33
+
34
+ "<td>#{html}</td>"
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,29 @@
1
+ require_relative "table"
2
+
3
+ module Spyro
4
+ module ActionViewExtension
5
+
6
+ module CollectionForHelper
7
+ module Output
8
+ class InplaceTable < Table
9
+ def initialize unicollection, helper, parser_class
10
+ raise "InplaceTable: Bad parser class (#{parser_class} instead of CollectionForHelper::Parser::Model)" if parser_class != CollectionForHelper::Parser::Model
11
+ super
12
+ end
13
+
14
+ def data_type elem
15
+ "input"
16
+ end
17
+
18
+ def custom_value_formatted value, elem
19
+ if elem.name.to_sym.in? [:header, :id, :created_at, :updated_at]
20
+ value
21
+ else
22
+ "<span class='best_in_place' data-type='#{data_type elem}' data-url='#{@unicollection.meta[:show]}' data-object='#{@unicollection.meta[:model_class].to_s.underscore}' data-attribute='#{elem.name}' data-type='input'>#{value}</span>"
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,22 @@
1
+ require_relative "base"
2
+
3
+ module Spyro
4
+ module ActionViewExtension
5
+
6
+ module CollectionForHelper
7
+ module Output
8
+ class Map < Output::Base
9
+ delegate :image_tag, to: :@h
10
+
11
+ def render
12
+ locations = @unicollection.rows.map do |r|
13
+ r[:data].map(&:value).join(', ')
14
+ end
15
+
16
+ image_tag "http://maps.googleapis.com/maps/api/staticmap?size=600x300&maptype=roadmap&sensor=false&#{locations.map {|location| "markers=#{location}"}.join('&')}"
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,126 @@
1
+ require_relative "base"
2
+ require_relative "fields"
3
+
4
+ module Spyro
5
+ module ActionViewExtension
6
+
7
+ module CollectionForHelper
8
+ module Output
9
+ class Table < Output::Base
10
+ delegate :link_to, :mini_button, :mini_button_success, :mini_button_danger, :mini_button_info, to: :@h
11
+
12
+ include Fields
13
+
14
+ def header
15
+ @header ||= (@unicollection.meta[:header] || []) + (@unicollection.meta[:actions] ? ['Actions'] : [])
16
+ end
17
+
18
+ def render_header
19
+ return "" unless @unicollection.meta[:header]
20
+ content_tag :thead, @unicollection.meta[:html_header] do
21
+ html = header.map do |header_sym|
22
+ header = t(header_sym)
23
+ header = @unicollection.meta[:block_header].call header_sym, header if @unicollection.meta[:block_header]
24
+ "<th>#{header}</th>"
25
+ end.join('')
26
+ "<tr>#{html}</tr>".html_safe
27
+ end
28
+ end
29
+
30
+ def default_destroy_link_attributes
31
+ {:data => {:confirm => "Are you sure?", :method => "delete", :'confirm-title' => "Confirmation"}}
32
+ end
33
+
34
+ def render_cell_buttons row
35
+ row[:meta][:actions] = {} if row[:meta][:actions].nil?
36
+
37
+ html = if row[:meta][:actions].is_a? Hash
38
+ (row[:meta][:actions] || []).map do |name, link|
39
+ case name
40
+ when :show
41
+ mini_button_success name, link
42
+ when :edit
43
+ mini_button_info name, link
44
+ when :destroy
45
+ mini_button_danger name, link, default_destroy_link_attributes
46
+ else
47
+ mini_button name, link
48
+ end
49
+ end.join ''
50
+ else
51
+ row[:meta][:actions]
52
+ end
53
+
54
+ "<td><span class='btn-group'>#{html}</span></td>"
55
+ end
56
+
57
+ def format_value value, elem
58
+ return self.send("format_#{elem.as}".to_sym, value, {}) if elem.as
59
+
60
+
61
+ @@fields.each do |keys, values|
62
+ klass, pattern = *keys
63
+ if (Symbol === klass and klass == elem.db_type) or (Class === klass and value.is_a? klass)
64
+ return self.send("format_#{values[:method]}".to_sym, value, {}) if elem.name.to_s.match pattern
65
+ end
66
+ end
67
+ value
68
+ end
69
+
70
+ def custom_value_formatted value, elem
71
+ value
72
+ end
73
+
74
+ def render_body
75
+ content = @unicollection.rows.map do |row|
76
+ html = row[:data].map do |elem|
77
+ value_formatted = elem.value
78
+ value_formatted = t(value_formatted) if elem.translate
79
+ value_formatted = format_value value_formatted, elem
80
+ value_formatted = link_to value_formatted, elem.link if elem.link
81
+ value_formatted = custom_value_formatted value_formatted, elem
82
+ elem.html ? content_tag(:td, value_formatted, elem.html) : "<td>#{value_formatted}</td>"
83
+ end.join('')
84
+ html += render_cell_buttons row if @unicollection.meta[:actions]
85
+ (row[:meta][:opts] and row[:meta][:opts][:html]) ? content_tag(:tr, html.html_safe, row[:meta][:opts][:html]) : "<tr>#{html}</tr>"
86
+ end.join('').html_safe
87
+
88
+ if @unicollection.meta[:header]
89
+ content_tag :tbody, @unicollection.meta[:html_body] do
90
+ content
91
+ end
92
+ else
93
+ content
94
+ end
95
+ end
96
+
97
+ def render_footer
98
+ return "" unless @unicollection.meta[:footer] and @unicollection.meta[:header]
99
+
100
+ total = header.count
101
+
102
+ content_tag :tfoot, @unicollection.meta[:html_footer] do
103
+ content = @unicollection.meta[:footer].map do |elem|
104
+ colspan = [(header.count / @unicollection.meta[:footer].count.to_f).ceil, total].min
105
+ total -= colspan
106
+ "<td colspan='#{colspan}'>#{elem}</td>"
107
+ end.join('')
108
+ "<tr>#{content}</tr>".html_safe
109
+ end
110
+ end
111
+
112
+ def render
113
+ return "" if @unicollection.rows.empty?
114
+ table_html_opts = {:class => ['table', self.class.to_s.demodulize.underscore]}.deep_merge(@unicollection.meta[:html] || {}) { |key, old, new| Array.wrap(old) + Array.wrap(new) }
115
+ content_tag :table, table_html_opts do
116
+ html = render_header.html_safe
117
+ html << render_body
118
+ html << render_footer
119
+ html
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,39 @@
1
+ require_relative "base"
2
+
3
+ module Spyro
4
+ module ActionViewExtension
5
+
6
+ module CollectionForHelper
7
+ module Output
8
+ class XLSX < Output::Base
9
+ def render_header sheet
10
+ return unless @unicollection.meta[:data]
11
+ sheet.add_row @unicollection.meta[:data]
12
+ end
13
+
14
+ def render_body sheet
15
+ @unicollection.rows.each do |row|
16
+ sheet.add_row row[:data].map(&:value)
17
+ end
18
+ end
19
+
20
+ def render
21
+ return "" if @unicollection.rows.empty?
22
+
23
+ filename = @unicollection.meta[:filename] || @unicollection.meta[:model_class] || "file"
24
+ xlsx_package = Axlsx::Package.new({})
25
+ wb = xlsx_package.workbook
26
+
27
+
28
+ wb.add_worksheet(name: filename) do |sheet|
29
+ render_header sheet
30
+ render_body sheet
31
+ end
32
+
33
+ xlsx_package.to_stream.string
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,22 @@
1
+ # require_relative "base"
2
+ # require_relative "active_record_relation"
3
+ # require_relative "../../../app/models/active_ldap"
4
+
5
+ # module Spyro
6
+ # module ActionViewExtension
7
+
8
+ # module CollectionForHelper
9
+ # module Parser
10
+ # class ActiveLdapRelation < ActiveRecordRelation
11
+ # @@types[::ActiveLDAP::Relation] = self
12
+
13
+ # def initialize *args
14
+ # super
15
+
16
+ # header [:id, :login, :email], :actions => true
17
+ # end
18
+ # end
19
+ # end
20
+ # end
21
+ # end
22
+ # end
@@ -0,0 +1,138 @@
1
+ require_relative "base"
2
+
3
+ module Spyro
4
+ module ActionViewExtension
5
+
6
+ module CollectionForHelper
7
+ module Parser
8
+ class ActiveRecordRelation < Parser::Base
9
+ @@types[::ActiveRecord::Relation] = self
10
+
11
+ def initialize collection, helper, options
12
+ super
13
+ end
14
+
15
+ def header args, opts = {}, &block
16
+ self.data args, opts, &block
17
+ end
18
+
19
+ def data args, opts = {}, &block
20
+ if args.is_a? ::Array
21
+ @unicollection.add_meta :data, args
22
+ else
23
+ @unicollection.add_meta :data, args.values.reduce(:+).uniq
24
+ args.each do |key, value|
25
+ @unicollection.add_meta "data-#{key}".to_sym, value
26
+ end
27
+ end
28
+
29
+ self.actions if opts[:actions]
30
+ @unicollection.add_meta :html_header, opts[:html]
31
+ @unicollection.add_meta :block_header, block if block_given?
32
+ end
33
+
34
+ def parse
35
+ unless @unicollection.has_meta? :data
36
+ @unicollection.add_meta :data, @collection.first.try(:attribute_names).try(:compact) || []
37
+ @unicollection.add_meta :actions, true
38
+ end
39
+
40
+ if @unicollection.rows.empty?
41
+ @collection.each do |model|
42
+ @unicollection.meta[:model_class] ||= model.class.to_s
43
+
44
+ @unicollection.row do |r|
45
+ @unicollection.meta[:data].each do |name|
46
+ hash = hash_for_name model, name
47
+ hash[:link] = link model if name == :name
48
+ r.add_elem UniData::Element.new(hash)
49
+ end
50
+ r.add_elem_meta :actions, populate_actions(model, r, @options, [:show, :edit, :destroy])
51
+ r.add_elem_meta :id, model.id
52
+ end
53
+ end
54
+ end
55
+
56
+ @unicollection.add_meta :header, @unicollection.meta[:data]
57
+ @unicollection.try_add_meta :footer, ["Total: #{@unicollection.rows.count}"]
58
+ end
59
+
60
+ def footer content, opts = {}
61
+ @unicollection.add_meta :footer, [*content]
62
+ @unicollection.add_meta :html_footer, opts[:html]
63
+ end
64
+
65
+ def populate_actions model, row, options, buttons
66
+ actions = {}
67
+
68
+ buttons.each do |button|
69
+ actions[:show] = polymorphic_path([*options[:parents], model]) rescue nil if button == :show
70
+ actions[:edit] = (actions[:show] ? "#{actions[:show]}/edit" : edit_polymorphic_path([*options[:parents], model])) rescue nil if button == :edit
71
+ actions[:destroy] = actions[:show] || polymorphic_path([*options[:parents], model]) rescue nil if button == :destroy
72
+ actions[button.keys.first] = button.values.first if button.is_a? Hash
73
+ end
74
+
75
+ actions.delete_if { |_, v| v.nil? }
76
+ end
77
+
78
+ def actions val = true
79
+ @unicollection.add_meta :actions, val
80
+ end
81
+
82
+ def body opts = {}, &block
83
+ def row opts
84
+ @r.add_elem_meta :opts, opts
85
+ end
86
+
87
+ @collection.each do |elem|
88
+ @unicollection.meta[:model_class] ||= elem.class.to_s
89
+ @unicollection.row do |r|
90
+ @elem = elem
91
+ @r = r
92
+ r.add_elem_meta :id, elem.id if elem.respond_to?(:id)
93
+ block.call elem
94
+ end
95
+ end
96
+
97
+ @unicollection.add_meta :html_body, opts[:html]
98
+ end
99
+
100
+ def cell value = nil, options = {}, &block
101
+ if value.is_a? Hash
102
+ options = value
103
+ value = nil
104
+ end
105
+
106
+ value = @h.capture(&block) || "" if block_given?
107
+
108
+ options[:link] = true if @unicollection.meta[:data] and @unicollection.meta[:data][@unicollection.rows.last[:data].count] == :name
109
+ options[:link] = link @elem if options[:link] == true
110
+
111
+ hash = if value
112
+ {value: value, type: String, name: "custom", db_type: String}
113
+ else
114
+ hash_for_name @elem, @unicollection.meta[:data][@unicollection.rows.last[:data].count]
115
+ end
116
+
117
+ @r.add_elem UniData::Element.new(hash.merge(options))
118
+ end
119
+
120
+ def buttons buttons = nil, opts = {}, &block
121
+ if block_given?
122
+ @r.add_elem_meta :actions, @h.capture(&block)
123
+ else
124
+ buttons = :all if buttons.nil?
125
+ buttons = [*buttons]
126
+ buttons.map! {|b| b == :all ? [:show, :edit, :destroy] : b}
127
+ buttons.flatten!
128
+ @r.add_elem_meta :actions, populate_actions(@elem, @r, @options, [*buttons])
129
+ end
130
+ end
131
+
132
+ alias_method :button, :buttons
133
+
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end