spyro 0.0.2

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 (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,3 @@
1
+ = header "#{t('scaffold.edit', :default => 'Edit')} #{resource.to_desc}" do
2
+ = group do
3
+ = button "#{t('scaffold.btn.index', :default => 'Index')}", collection_url rescue nil if can? :index, resource_class
@@ -0,0 +1,11 @@
1
+ - fields.each do |field|
2
+ - if field =~ /_at$/ or field =~ /^date/
3
+ = f.input field, :as => :datetimepicker, :input_html => {:value => l(resource.send(field.to_sym).present? ? resource.send(field.to_sym) : Date.today, :format => :datetime)}
4
+ - elsif defined?(ClassyEnum::Base) and params[:id] and resource.send(field.to_sym).class < ClassyEnum::Base
5
+ = f.input field, as: :select, collection: field.to_s.classify.constantize.select_options
6
+ - elsif field =~ /(.+)_id$/
7
+ = f.association $1.to_sym, :label_method => :to_desc, as: :chosen if params[field.to_sym].nil?
8
+ - elsif field =~ /(.+)_html$/
9
+ = f.input field, :input_html => {:rows => 10, :cols => 10}
10
+ - else
11
+ = f.input field
@@ -0,0 +1,6 @@
1
+ = simple_form_for [*parents, resource] do |f|
2
+ .form-inputs
3
+ = render :partial => "fields", :locals => {fields: resource.usefull_attribute_names, f: f}
4
+ = render :partial => "other_form_fields", :locals => {f: f}
5
+ .form-actions
6
+ = f.submit
@@ -0,0 +1,4 @@
1
+ = header resource_class.to_s.humanize.pluralize.titleize do
2
+ = group do
3
+ = button "#{t('scaffold.btn.create', :default => 'Create')}", new_polymorphic_path([*parents, resource_class]) rescue nil if can? :new, resource_class
4
+ = download_mime_type_btns
@@ -0,0 +1,3 @@
1
+ = header "#{t('scaffold.create', :default => 'Create new')} " + resource_class.to_s.humanize do
2
+ = group do
3
+ = button "#{t('scaffold.btn.index', :default => 'Index')}", collection_url rescue nil if can? :index, resource_class
@@ -0,0 +1,9 @@
1
+ = header resource.to_desc do
2
+ = group do
3
+ - resource_class.reflections.dup.keep_if {|s, r| s and r.macro == :has_many}.each do |symbol, reflection|
4
+ = button "#{t('scaffold.btn.index', :default => symbol.to_s.humanize)}", polymorphic_path([*parents, resource, symbol]) rescue nil if can? :index, symbol
5
+ = group do
6
+ = button "#{t('scaffold.btn.index', :default => 'Index')}", collection_url rescue nil if can? :index, resource_class
7
+ = button "#{t('scaffold.btn.create_new', :default => 'Create new one')}", new_polymorphic_path([*parents, resource_class]) rescue nil if can? :new, resource_class
8
+ = button "#{t('scaffold.btn.edit', :default => 'Edit')}", edit_polymorphic_path([*parents, resource]) rescue nil if can? :edit, resource
9
+ = button_danger "#{t('scaffold.btn.destroy', :default => 'Destroy')}", polymorphic_path([*parents, resource]), default_destroy_link_attributes if can? :destroy, resource
@@ -0,0 +1,5 @@
1
+ = tabs do
2
+ - tab "File" do
3
+ = f.input 'file', :as => :file, error: @parser.try(:errors).try(:to_s)
4
+ - tab "Content" do
5
+ = f.input 'content', :as => :text, input_html: {value: @parser.try(:text)}
@@ -0,0 +1,10 @@
1
+ - if Rails.env.development? and @dup and @dup.errors.any?
2
+ %pre
3
+ - fct = -> (elem) { elem.errors.messages.inspect + ", " + elem.errors.messages.keys.map {|c| [*elem.send(c.to_sym)].map {|e| "#{c} => #{fct.call(e)}" }.join(', ') }.join(', ')}
4
+ = fct.call @dup
5
+
6
+ = simple_form_for resource, url: params.slice(:action, :controller) do |f|
7
+ .form-inputs
8
+ = render :partial => "fields", :locals => {fields: resource.copiable_args[:except], f: f}
9
+ .form-actions
10
+ = f.submit
@@ -0,0 +1,4 @@
1
+ .container-item
2
+ = render "edit_header"
3
+
4
+ = render "form"
@@ -0,0 +1,8 @@
1
+ - if collection.any?
2
+ - {:options => {}, :column_names => collection.first.attributes.keys, :header => true}.each do |key, default|
3
+ - instance_variable_set("@#{key}", (resource_class.respond_to?("csv_#{key}".to_sym) ? resource_class.send("csv_#{key}".to_sym) : default))
4
+
5
+ = collection_for collection, output: :CSV do |t|
6
+ - t.header @column_names.collect {|elem| Hash === elem ? elem.keys.first : elem} if @header
7
+ - t.body do |elem|
8
+ - elem.attributes.values_at(*@column_names.collect {|elem| Hash === elem ? elem.values.first.to_s : elem.to_s}).each { |value| t.cell value}
@@ -0,0 +1,7 @@
1
+ .container-item
2
+ = render :partial => "index_header"
3
+
4
+
5
+
6
+ #main-container
7
+ = react_component('Collection', {collection: collection})
@@ -0,0 +1,2 @@
1
+ - html = escape_javascript(render(:partial => 'table'))
2
+ = "$('#main-container').html('#{html}');".html_safe
@@ -0,0 +1,12 @@
1
+ if collection.any?
2
+ {:options => {}, :column_names => collection.first.attributes.keys, :header => true}.each do |key, default|
3
+ instance_variable_set("@#{key}", (resource_class.respond_to?("xls_#{key}".to_sym) ? resource_class.send("xls_#{key}".to_sym) : default))
4
+ end
5
+
6
+ collection_for collection, :output => :XLSX do |t|
7
+ t.header @column_names.collect {|elem| Hash === elem ? elem.keys.first : elem} if @header
8
+ t.body do |elem|
9
+ elem.attributes.values_at(*@column_names.collect {|elem| Hash === elem ? elem.values.first.to_s : elem.to_s}).each { |value| t.cell value}
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,46 @@
1
+ - @vals ||= {}
2
+ - explanation = (parents.last ? "to users of #{parents.last.class.to_s.humanize} #{parents.last.to_desc}" : "")
3
+ - explanation << " (#{collection.count('id')} users"
4
+ - explanation << " + #{@campus.main_email}" if @campus and @campus.main_email
5
+ - explanation << ")"
6
+ .container-item
7
+ .mailer-title
8
+ %h3.main-title.primary= "Send a mail #{explanation.downcase}"
9
+ .mailer-content.row
10
+ .mailer-form.col-md-6
11
+ = simple_form_for :mailer, url: polymorphic_path([:mailer, *parents, User]) do |f|
12
+ = f.input :from, :input_html => {:value => (@vals[:from] || "#{User.current_user.login.titleize} <#{User.current_user.email}>")}, hint: "Must be formatted as 'name <email@somewhere>'", required: true
13
+ = f.input :subject, :input_html => {:value => @vals[:subject]}, required: true
14
+ = f.input :title, :input_html => {:value => @vals[:title]}, hint: "If not specified, will be the mail subject. Must be short, and please avoid using '[' or braces.", required: false
15
+ = f.input :subtitle, :input_html => {:value => @vals[:subtitle]}, hint: "Optional, use it if the mail title exceeds 32 characters.", required: false
16
+ -# = f.input :subtitle, :input_html => {:value => @vals[:subtitle]}
17
+ = f.input :content, :as => :text, :input_html => {:value => @vals[:content]}, hint: "Supports Markdown", required: true
18
+ = f.input :campus_ids, :as => :chosen, label_method: -> (c) { c.main_email ? "#{c.name} (+ #{c.main_email})" : c.name}, :selected => (@vals[:campus_ids] || [User.current_user.campus.id]), :collection => Campus.all, label: "Send to campus", required: true if params[:campus_id].nil?
19
+ = f.submit
20
+ .mailer-preview.col-md-6
21
+ .main-mail-headers
22
+ .mail-from
23
+ From:
24
+ %span{data: {:'simple-preview' => '#mailer_from'}}= (@vals[:from] || "#{User.current_user.login.titleize} <#{User.current_user.email}>")
25
+ .mail-subject
26
+ Subject:
27
+ %span{data: {:'simple-preview' => '#mailer_subject'}}= @vals[:subject]
28
+ .main-preview
29
+ %header
30
+ %img{alt: "logo42", src: "https://cdn.intra.42.fr/mailer/logo_small.png"}
31
+ %h2{data: {:'markdown-preview' => '#mailer_title'}}
32
+ %h4{data: {:'markdown-preview' => '#mailer_subtitle'}}
33
+ %section
34
+ %p{data: {:'markdown-preview' => '#mailer_content'}}
35
+ %footer
36
+ %header
37
+ This email was sent by
38
+ %a{href: "http://www.42.fr"} 42
39
+ %span • 96 boulevard Bessières • 75017 Paris
40
+ %aside
41
+ %a{href: "http://Facebook.com/42born2code"}
42
+ %img{alt: "follow us on facebook", src: "https://cdn.intra.42.fr/mailer/facebook_small.png"}/
43
+ %a{href: "https://twitter.com/42born2code"}
44
+ %img{alt: "follow us on twitter", src: "https://cdn.intra.42.fr/mailer/twitter_small.png"}/
45
+ %a{href: "https://www.google.com/+42Frborn2code"}
46
+ %img{alt: "follow us on google", src: "https://cdn.intra.42.fr/mailer/google_small.png"}/
@@ -0,0 +1,4 @@
1
+ .container-item
2
+ = render "new_header"
3
+
4
+ = render "form"
@@ -0,0 +1,11 @@
1
+ - explanation = (parents.last ? "to users of #{parents.last.class.to_s.humanize} #{parents.last.to_desc}" : "")
2
+ .container-item
3
+ .mailer-title
4
+ %h3.main-title.primary= "Send a notification #{explanation.downcase}"
5
+ .mailer-form
6
+ = simple_form_for :notify, url: polymorphic_path([:notify, *parents, User]) do |f|
7
+ = f.input :title
8
+ = f.input :text, :as => :text
9
+ = f.input :campus_ids, :as => :chosen, :selected => (params[:campus_id] || [User.current_user.campus.id]), :collection => Campus.all, label: "Send to campus", required: true
10
+
11
+ = f.submit
@@ -0,0 +1,8 @@
1
+ .container-item
2
+ = render :partial => "show_header"
3
+
4
+ = render :partial => "details"
5
+
6
+ = render :partial => "custom"
7
+
8
+ = render :partial => "associations"
@@ -0,0 +1,36 @@
1
+ = render "index_header"
2
+
3
+ - resource_class.columns.group_by { |col| col.type }.each do |type, cols|
4
+ - if type == :boolean
5
+ - cols.each do |col|
6
+ - prcts = resource_class.group(col.name).count.map {|k,v| [{true => "Yes", false => "No"}[k], v]}.to_h
7
+ - chart = LazyHighCharts::HighChart.new('graph') do |f|
8
+ - f.title(:text => "#{col.name.humanize} repartition")
9
+ - f.series(:name => col.name, :data => prcts.to_a)
10
+ - f.chart({:defaultSeriesType => "pie"})
11
+ .col-md-6
12
+ = high_chart("graph-#{col.name}", chart)
13
+
14
+
15
+ - if type == :datetime
16
+ - cols.each do |col|
17
+ - dates = resource_class.group_by_day(col.name).count.map {|k,v| [k.to_date, v]}.to_h
18
+ - chart = LazyHighCharts::HighChart.new('graph') do |f|
19
+ - f.title(:text => "#{col.name.humanize} repartition")
20
+ - f.xAxis(:categories => dates.keys, tickInterval: 10)
21
+ - f.series(:name => col.name, :data => dates.values)
22
+ - f.chart({:defaultSeriesType => "line"})
23
+ .col-md-12
24
+ = high_chart("graph-#{col.name}", chart)
25
+
26
+
27
+ - if type == :string
28
+ - cols.each do |col|
29
+ - if resource_class.new.send(col.name).class < ClassyEnum::Base
30
+ - prcts = resource_class.group(col.name).count
31
+ - chart = LazyHighCharts::HighChart.new('graph') do |f|
32
+ - f.title(:text => "#{col.name.humanize} repartition")
33
+ - f.series(:name => col.name, :data => prcts.to_a)
34
+ - f.chart({:defaultSeriesType => "pie"})
35
+ .col-md-6
36
+ = high_chart("graph-#{col.name}", chart)
@@ -0,0 +1 @@
1
+ = render :partial => "shared/trombi", :locals => {:users => collection}
@@ -0,0 +1,24 @@
1
+ .container-item
2
+ = render 'new_header'
3
+
4
+ - if @parser
5
+ :preserve
6
+ #{@parser.class.to_doc}
7
+ - if (flash and flash.any?) || @parser.errors.any?
8
+ .upload-errors
9
+ .panel.panel-default
10
+ .panel-body{data: {import: {errors: @parser.errors.to_json, text: params.fetch(:user, {}).fetch("content", nil)}}}
11
+ %h4= "Importation ended with #{flash.map{|f, m| '<span class="text-' + (f == 'error' ? 'danger' : f) + '">' + m + '</span>'}.join(', ')}".html_safe
12
+ %ul
13
+ - @parser.errors.each do |line, error|
14
+ %li
15
+ %b= "line #{line + 1}"
16
+ = error.map{|e| e[:error]}.join(", ")
17
+ -# = raise "lol"
18
+
19
+
20
+
21
+ = simple_form_for resource_class.to_s.underscore.to_sym, :html => {:class => ""}, url: url_for(basic_params.merge(:action => :upload)) do |f|
22
+ = render :partial => 'upload_fields', :locals => {f: f}
23
+ = f.submit
24
+ -# = raise "lol"
@@ -0,0 +1 @@
1
+ Rails.application.config.assets.precompile += %w( spyro.js )
@@ -0,0 +1,2 @@
1
+ Spyro::Engine.routes.draw do
2
+ end
@@ -0,0 +1,24 @@
1
+ require "spyro/engine"
2
+
3
+ module Spyro
4
+
5
+
6
+ Dir[File.dirname(__FILE__) + "/spyro/collections/**/*.rb"].each do |file|
7
+ p "🐲 require #{file}"
8
+ require file
9
+ end
10
+
11
+ require "spyro/helpers/action_view_extension"
12
+ require "spyro/usefull_attributes"
13
+ require "spyro/namespace_template_inheritance"
14
+ require "spyro/filters_controller_add_on"
15
+ require "spyro/application_controller_add_on"
16
+ require "spyro/active_record_add_on"
17
+ require "spyro/controllers/strong_parameted"
18
+
19
+ ActiveSupport.on_load(:action_view) do
20
+ ::ActionView::Base.send :include, Spyro::ActionViewExtension
21
+
22
+ ::ActiveRecord::Base.send(:include, UsefullAttributesExtension)
23
+ end
24
+ end
@@ -0,0 +1,38 @@
1
+ module ActiveRecord
2
+ class Base
3
+ def self.primary_key
4
+ "id"
5
+ end
6
+
7
+ def primary_key
8
+ "id"
9
+ end
10
+
11
+ def to_desc *args
12
+ self.send self.to_desc_sym *args
13
+ end
14
+
15
+ def to_desc_sym *args
16
+ self.respond_to?(:name) ? :name : :id
17
+ end
18
+
19
+ def self.default field, value, opts = {}
20
+ opts = {:forced => false, :method => :blank?, :action => :before_validation}.merge opts
21
+ fct = "#{field}_#{opts[:action]}".to_sym
22
+
23
+ self.send(opts[:action], fct)
24
+
25
+ define_method fct do
26
+ return true if opts[:if] and not opts[:if].call(*(opts[:if].arity.zero? ? [] : [self]))
27
+ return true if opts[:unless] and opts[:unless].call(*(opts[:unless].arity.zero? ? [] : [self]))
28
+
29
+ if opts[:forced] == true or self.send(field.to_sym).send(opts[:method])
30
+ final_value = value.respond_to?(:call) ? value.call(*(value.arity.zero? ? [] : [self])) : value
31
+ self.send("#{field.to_sym}=", final_value)
32
+ end
33
+
34
+ true
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,24 @@
1
+ require "cancan"
2
+
3
+ # This module is not loaded in API anymore
4
+ module ApplicationControllerAddOn
5
+ extend ActiveSupport::Concern
6
+
7
+ def self.included daddy
8
+ daddy.before_filter :namespace_view_path
9
+ end
10
+
11
+ def class_namespace
12
+ @class_namespace ||= self.class.to_s.split('::').first.downcase.to_sym
13
+ end
14
+
15
+ def namespace_view_path
16
+ append_view_path "#{File.dirname(__FILE__)}/../../app/views/locker"
17
+ append_view_path NamespaceTemplateInheritance.new(class_namespace)
18
+ append_view_path GemNamespaceTemplateInheritance.new(class_namespace)
19
+ end
20
+ end
21
+
22
+ class ActionController::Base
23
+ include ApplicationControllerAddOn
24
+ end
@@ -0,0 +1,28 @@
1
+ require_relative "table"
2
+
3
+ module Spyro
4
+ module ActionViewExtension
5
+
6
+ module CollectionForHelper
7
+ module Output
8
+ class AdminTable < Table
9
+ delegate :mini_button_error, to: :@h
10
+
11
+
12
+ def initialize unicollection, helper, parser_class
13
+ super
14
+ unicollection.meta[:html] ||= {}
15
+ unicollection.meta[:html][:'data-model'] = unicollection.meta[:model_class].try(:underscore)
16
+ unicollection.meta[:header] = ['<input type="checkbox" class="select all">'] + unicollection.meta[:header]
17
+ unicollection.meta[:footer] = ["<span class='pull-left'>#{unicollection.meta[:footer].join}</span><span class='pull-right btns btn-group'>#{[*(unicollection.meta[:multiple_buttons] || unicollection.meta[:multiple_button])].join}</span>"]
18
+
19
+ @unicollection.rows.each do |row|
20
+ row[:data] = [UniData::Element.new(value: "<input type='checkbox' class='select one' data-id='#{row[:meta][:id]}'>", type: String, name: 'checkbox', db_type: String)] + row[:data]
21
+ end
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,46 @@
1
+ require_relative "base"
2
+
3
+
4
+ module Spyro
5
+ module ActionViewExtension
6
+
7
+ module CollectionForHelper
8
+ module Output
9
+ class BarGraphTable < Output::Base
10
+ def initialize unicollection, helper, parser_class
11
+ super unicollection, helper, parser_class
12
+ end
13
+
14
+ def format_prct value
15
+ @min ||= @unicollection.meta[:min] || 0
16
+ @max ||= @unicollection.meta[:max] || 100
17
+
18
+ [[(value - @min) * 100 / (@max - @min), 0].max, 100].min
19
+ end
20
+
21
+ def build_popover title, popovers
22
+ "class='has-popover' data-title='#{title}' data-html='true' data-content='#{popovers.map {|elem| elem.join(': ')}.join('<br/>')}'"
23
+ end
24
+
25
+ def render
26
+ html = @unicollection.rows.map do |row|
27
+ html_row = row[:'data'].map do |elem|
28
+ @unicollection.meta[:'data-primary'].include?(elem.name.to_sym) ? elem.value : nil
29
+ end.compact
30
+
31
+ popovers = row[:'data'].map do |elem|
32
+ @unicollection.meta[:'data-secondary'].include?(elem.name.to_sym) ? elem.value : nil
33
+ end.compact
34
+
35
+ title = html_row.first
36
+ value = html_row.last
37
+ span = "<span style='position: absolute; left: 10px; color: black'>#{html_row[0..-2].join ' - '}</span><span style='position: absolute; right: 10px; color: black'>#{value}</span>"
38
+ "<li #{build_popover(title, @unicollection.meta[:'data-secondary'].zip(popovers))}><div class='progress progress-info' style='position: relative'><div class='progress-bar' style='width: #{self.format_prct(value)}%'>#{span}</div></div></li>".html_safe
39
+ end.join('')
40
+ "<ul class='list-unstyled'>#{html}</ul>".html_safe
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,23 @@
1
+
2
+
3
+ module Spyro
4
+ module ActionViewExtension
5
+ module CollectionForHelper
6
+ module Output
7
+ class Base
8
+ delegate :params, :content_tag, to: :@h
9
+
10
+ def initialize unicollection, helper, parser_class
11
+ @unicollection = unicollection
12
+ @h = helper
13
+ @parser_class = parser_class
14
+ end
15
+
16
+ def t name
17
+ I18n.t("#{params[:controller].gsub('/', '.')}.#{params[:action]}.table.#{name.downcase}", :default => I18n.t("scaffold.table.#{name.downcase}", :default => name.to_s.humanize))
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end