best_boy 2.2.3 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +74 -110
  3. data/app/assets/javascripts/best_boy/best_boy.js +0 -1
  4. data/app/assets/stylesheets/best_boy/base.sass +21 -0
  5. data/app/assets/stylesheets/best_boy/best_boy.css +1 -3
  6. data/app/controllers/best_boy/{best_boy_events_controller.rb → events_controller.rb} +4 -4
  7. data/{lib/best_boy/models/active_record → app/models}/best_boy/day_report.rb +0 -0
  8. data/app/models/best_boy/event.rb +29 -0
  9. data/{lib/best_boy/models/active_record → app/models}/best_boy/month_report.rb +0 -0
  10. data/app/views/best_boy/events/_navigation.html.erb +11 -0
  11. data/app/views/best_boy/events/charts.html.erb +33 -0
  12. data/app/views/best_boy/events/details.html.erb +98 -0
  13. data/app/views/best_boy/events/details.xml.haml +22 -0
  14. data/app/views/best_boy/events/index.html.erb +8 -0
  15. data/app/views/best_boy/events/lists.html.erb +62 -0
  16. data/app/views/best_boy/events/lists.xml.haml +8 -0
  17. data/app/views/best_boy/events/monthly_details.html.erb +67 -0
  18. data/app/views/best_boy/events/monthly_details.xml.haml +15 -0
  19. data/app/views/best_boy/events/stats.html.erb +89 -0
  20. data/app/views/best_boy/events/stats.xml.haml +18 -0
  21. data/app/views/layouts/best_boy/best_boy.html.erb +43 -0
  22. data/config/routes.rb +13 -7
  23. data/db/migrate/20150610155237_create_best_boy_events.rb +17 -0
  24. data/db/migrate/20150610155251_create_best_boy_reports.rb +28 -0
  25. data/lib/best_boy.rb +8 -5
  26. data/lib/best_boy/{controllers/best_boy_controller.rb → controller.rb} +6 -3
  27. data/lib/best_boy/engine.rb +7 -27
  28. data/lib/best_boy/{models/active_record/best_boy/eventable.rb → eventable.rb} +7 -6
  29. data/lib/best_boy/{models/active_record/best_boy/obeys_test_mode.rb → obeys_test_mode.rb} +0 -0
  30. data/lib/best_boy/{models/active_record/best_boy/reporting.rb → reporting.rb} +0 -0
  31. data/lib/best_boy/version.rb +1 -1
  32. data/lib/generators/best_boy/install_generator.rb +11 -0
  33. data/lib/generators/{templates → best_boy/templates/config/initializers}/best_boy.rb +0 -6
  34. data/lib/tasks/recover_report_history.rake +7 -7
  35. metadata +64 -71
  36. data/app/assets/images/best_boy/glyphicons-halflings-white.png +0 -0
  37. data/app/assets/images/best_boy/glyphicons-halflings.png +0 -0
  38. data/app/assets/javascripts/best_boy/bootstrap_datepicker.js +0 -401
  39. data/app/assets/stylesheets/best_boy/bootstrap.scss +0 -4983
  40. data/app/assets/stylesheets/best_boy/bootstrap_datepicker.css +0 -156
  41. data/app/views/best_boy/best_boy_events/_navigation.html.erb +0 -9
  42. data/app/views/best_boy/best_boy_events/charts.html.erb +0 -25
  43. data/app/views/best_boy/best_boy_events/details.html.erb +0 -88
  44. data/app/views/best_boy/best_boy_events/index.html.erb +0 -6
  45. data/app/views/best_boy/best_boy_events/lists.html.erb +0 -45
  46. data/app/views/best_boy/best_boy_events/monthly_details.html.erb +0 -51
  47. data/app/views/best_boy/best_boy_events/stats.html.erb +0 -80
  48. data/app/views/layouts/best_boy_backend.html.erb +0 -70
  49. data/lib/best_boy/models/active_record/best_boy_event.rb +0 -21
  50. data/lib/generators/active_record/best_boy_generator.rb +0 -29
  51. data/lib/generators/active_record/templates/add_event_source_to_best_boy_events_table.rb +0 -11
  52. data/lib/generators/active_record/templates/create_best_boy_events_table.rb +0 -17
  53. data/lib/generators/active_record/templates/create_best_boy_reports.rb +0 -30
  54. data/lib/generators/best_boy_generator.rb +0 -23
  55. data/lib/generators/templates/bootstrap/bootstrap.css +0 -4983
  56. data/lib/generators/templates/bootstrap/bootstrap_datepicker.css +0 -156
  57. data/lib/generators/templates/bootstrap/bootstrap_datepicker.js +0 -401
  58. data/lib/generators/templates/bootstrap/glyphicons-halflings-white.png +0 -0
  59. data/lib/generators/templates/bootstrap/glyphicons-halflings.png +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 00c48525e82d4a49337c3940ecf10eb160d8dd1a
4
- data.tar.gz: 412a38e42807d9fe19fa22667bc668feff7833c3
3
+ metadata.gz: 60316e2e138902bed41149f69236093c10dc2b42
4
+ data.tar.gz: 345c8c5a0ccd9f0652e823019e6f0d87a179a1ce
5
5
  SHA512:
6
- metadata.gz: 43395b950a37ae16e7ae958e4c252b37d4651cdcb828bfdbd092d1542e2f7122202e1541e53effd78ec457af1920b0b8e84cffe7b5e66f92135bf0f9db76c91c
7
- data.tar.gz: d687c76b054a487e8f27a8f165dc8ad30c205d284971526c97e89447a8ea56599f83b301910fc62a0b91c775b58384a85314873ae9ee1514213b64ac23ea2a85
6
+ metadata.gz: b917b25c4104b2e57ddf5e6bb752fc44d5be357f48913ac42d8609f767b1e8ee5aaa3dacb90dc51671f826da60571f7789fec3d878b2bfa048535981b3bd8a26
7
+ data.tar.gz: 4192cdb814d7f125b2be3bb41d32aa9e8d357cd20905cfd4bfb935926d3784138f9e291c779f1cb26cb72f180fdc320feb633160bf97ad260749e8829a36a202
data/README.md CHANGED
@@ -6,20 +6,29 @@ best_boy
6
6
  [![best_boy API Documentation](https://www.omniref.com/ruby/gems/best_boy.png)](https://www.omniref.com/ruby/gems/best_boy)
7
7
 
8
8
  A simple event driven logging for ActiveRecord models.
9
+ BestBoy is able to log model-based "create", "update" and "delete" events as well as custom events triggered in controller actions.
10
+ It uses its own polymorphic database table to log each event.
9
11
 
10
12
 
11
- What does this gem do?
13
+ Rails version support
12
14
  ----------------------
13
15
 
14
- best_boy logs "create" and "delete" events as well as custom events triggered by controller actions. It uses its own polymorphic database table to log each event.
15
- At the moment, best_boy only provides support for ActiveRecord models.
16
+ BestBoy 3 and above only supports Rails >= 4.1
16
17
 
17
18
 
18
- Rails version support
19
+ Changes in version 3
19
20
  ----------------------
20
21
 
21
- best_boy supports rails 3.2.x in its versions 1.1.x. At this point there is a feature stop and it will only provide fixes for its current features.
22
- Rails 4.0 support is provided in best_boy's versions 1.2.0 up to the current version.
22
+ Best Boy version 3 comes with some backward incompatible changes. However, it's totally worth it because BestBoy now follows all the best practices of a rails engine.
23
+ This and additional changes of version 3 include
24
+
25
+ * Uses rails engine naming conventions with an isolated ``BestBoy`` namespace
26
+ * serving the necessary migrations from the engines migration folder
27
+ * serving all assets via the asset pipeline (used to be a opt-in before)
28
+ * removes unnecessary generator boilerplate and config options
29
+ * uses the newest Bootstrap version (3)
30
+ * allows per class extending instead of polluting the whole app
31
+ * answers to xml requests for easy EXCEL integration
23
32
 
24
33
 
25
34
  Installation
@@ -33,93 +42,18 @@ Install it with Bundler
33
42
 
34
43
  bundle install
35
44
 
36
- If you do NOT want to use the asset-pipeline, run the generator as followed
37
-
38
- rails g best_boy
39
-
40
- This will install following files into your application
41
-
42
- config/initializers/best_boy.rb
43
-
44
- db_migrate/create_best_boy_events_table.rb
45
-
46
- public/javascripts/bootstrap_datepicker.js
47
-
48
- public/stylesheets/bootstrap.css
49
-
50
- public/stylesheets/bootstrap_datepicker.css
51
-
52
- In case you want the gem be compatible with the asset-pipeline, add a flag to the generator call:
53
-
54
- rails g best_boy --asset
55
-
56
- See usage section for version information.
57
-
58
- Run the migration
59
-
60
- rake db:migrate
61
-
62
-
63
- Changelog
64
- ---------
65
- #### 2.2.3
66
- * Rename ``report``method to a more best_boy specific ``trigger_best_boy_event_report`
67
-
68
- #### 2.2.2
69
- * Fix dependency bug with kaminari
70
-
71
- #### 2.2.1
72
- * flexibilized report creation method to create reports for a specific date
73
- * no compatibility with Ruby 1.9.3
74
-
75
- #### 2.2.0
76
- * Updated dependencies for rspec and kaminari
77
- * Make recover_report_history rake task a noop for no previously tracked BestBoyEvents
78
- * Bugfix for report recovery rake task
79
- * use appraisal for testing against different gemsets and Ruby versions
80
-
81
- #### 2.1.3
82
- * Compatible with Rails 4.1
83
- * Loosened kaminari dependency requirements
84
-
85
- #### 2.1.0
86
- * Code cleanup - now compatible with RSpec 3 syntax
87
- * Support a "dry-run" test mode
88
- * Reduce public methods added by `BestBoy::Eventable` ([#4](https://github.com/Absolventa/best_boy/issues/4))
89
- * Remove mass-assignments that could cause problems with the protected_attributes gem [#8](https://github.com/Absolventa/best_boy/issues/8)
90
- * Do not expose mixed-in controller method ([#9](https://github.com/Absolventa/best_boy/issues/9)))
91
- * Avoid potential name clashes for callbacks switch ([#10](https://github.com/Absolventa/best_boy/issues/10))
92
-
93
-
94
- Upgrading to Version 2
95
- --------------------------------
96
-
97
- From v2.x, BestBoy uses aggregated tables for the admin panel. You need
98
- to copy the new migrations to your app by running
99
-
100
- rails g best_boy --asset
101
-
102
- again. This generator will also ask you to overwrite your existing initializer - just
103
- reject this pressing 'n' for not overwriting your settings. Don't forget to run
104
-
105
- rake db:migrate
106
-
107
- and
45
+ Install the migrations
108
46
 
109
- rake best_boy:recover_report_history
110
-
111
- in the context of your mother app afterwards. See also section "Some thoughts about Performance"
112
- for more details about new data organization.
47
+ rake best_boy:install:migrations
113
48
 
49
+ Mount the best boy backend in your routes.rb
114
50
 
115
- Update to fit the asset-pipeline
116
- --------------------------------
51
+ mount BestBoy::Engine => "/best_boy"
117
52
 
118
- If you were using the gem without asset-pipeline and want to update your project to fit new rails versions, simply delete all best_boy files in your public folder.
53
+ Run the generator to create your best_boy config file:
119
54
 
120
- If you need to precompile assets, maybe for deployment on heroku cedar stack, please add the following flag to your best_boy initializer.
55
+ rails g best_boy:install
121
56
 
122
- config.precompile_assets = true
123
57
 
124
58
 
125
59
  Usage
@@ -127,21 +61,28 @@ Usage
127
61
 
128
62
  In model context:
129
63
 
64
+ include BestBoy::Eventable
130
65
  has_a_best_boy
131
66
 
132
- This will log "create" and "delete" event for each instance.
67
+ This will log "create" and "delete" events for each instance.
133
68
 
134
- If you do not want to selflog create and delete events, maybe because you will sort it semantically with a create source, just deactivate the callback logging by setting the parameter :disable_callbacks to true.
69
+ If you do not want to selflog those events, maybe because you will sort it semantically with a create source, just deactivate the callback logging by setting the parameter :disable_callbacks to true.
135
70
 
136
- has_a_best_boy :disable_callbacks => true
71
+ include BestBoy::Eventable
72
+ has_a_best_boy disable_callbacks: true
137
73
 
138
74
  In controller context:
139
75
 
76
+ # in application_controller.rb or the relevant controller
77
+ include BestBoy::Controller
78
+
79
+ # in a resource specific controller
140
80
  best_boy_event object, event, event_source = nil
141
81
 
142
- This will log custom events for a object and a event phrase. You can specify this event with a event_source parameter to log maybe seperate create actions.
82
+ This will log custom events for an object and an event phrase. You can specify this event with an event_source parameter to log maybe seperate create actions.
83
+
84
+ If no object or event is given an exception will be raised.
143
85
 
144
- If no Object is given, it will raise an exception as well as if no event is provided.
145
86
 
146
87
  #### Test mode
147
88
 
@@ -162,15 +103,6 @@ Conversely, you can also sandbox a specific code block:
162
103
  end
163
104
 
164
105
 
165
- BestBoyEvent table
166
- ------------------
167
-
168
- t.integer "owner_id" # owner model id
169
- t.string "owner_type" # owner model class type
170
- t.string "event" # event (create, delete)
171
- t.string "event_source" # event_source parameter for specific action tracking
172
- t.datetime "updated_at" # last update timestamp
173
- t.datetime "created_at" # creation timestamp
174
106
 
175
107
  Getting BestBoyEvents
176
108
  ---------------------
@@ -179,17 +111,12 @@ BestBoy comes with an admin interface, largely configurable to fit right into yo
179
111
 
180
112
  Following configurations can be done:
181
113
 
182
- config.precompile_assets "boolean" # default: false # if you need best_boy to precompile its assets for the asset-pipeline
183
- config.orm "symbole" # default: :active_record # for now only active_record is supported
184
114
  config.base_controller "String" # default: "ApplicationController" # declare with Controller should be inherited
185
115
  config.before_filter "comma separated symbols" # default: nil # declare before_filter to use inherited before_filters in admin section
186
116
  config.skip_before_filter "comma separated symbols" # default: nil # declare skip_before_filter to skip inherited before_filters in admin section
187
117
  config.skip_after_filter "comma separated symbols" # default: nil # declare skip_after_filter to skip inherited after_filters in admin section
188
118
  config.custom_redirect "relative path as String" # default: nil # set a path to return back to your existing backend
189
119
 
190
- After installation you can access it through:
191
-
192
- <your application path>/best_boy_admin
193
120
 
194
121
  Some thoughts about Performance
195
122
  -------------------------------
@@ -207,21 +134,58 @@ If you're upgrading BestBoy from an older version, there
207
134
  is a rake task for 'recovering' these report structure for
208
135
  an existing set of events. Simply run
209
136
 
210
- bundle exec rake best_boy:recover_report_history
137
+ rake best_boy:recover_report_history
211
138
 
212
139
  If you want to recover this report structure not for the whole lifetime,
213
140
  you can pass a date as argument to the rake task call:
214
141
 
215
- bundle exec rake best_boy:recover_report_history['2010-02-01']
142
+ rake best_boy:recover_report_history['2010-02-01']
216
143
 
217
144
  The latter would destroy and recover the all reports created after
218
145
  beginning of Feb 1st, 2010 up to now.
219
146
 
220
147
  Budget some time for this task, since it can take long if your BestBoyEvent table has grown very big.
221
148
 
149
+
150
+ Changelog
151
+ ---------
152
+ #### 3.0.0
153
+ * Major engine cleanup. Aims Rails >= 4.1 from now on.
154
+ * Includes backward incompatible changes. See above hint for more information.
155
+
156
+ #### 2.2.3
157
+ * Rename ``report`` method to a more best_boy specific ``trigger_best_boy_event_report`
158
+
159
+ #### 2.2.2
160
+ * Fix dependency bug with kaminari
161
+
162
+ #### 2.2.1
163
+ * flexibilized report creation method to create reports for a specific date
164
+ * no compatibility with Ruby 1.9.3
165
+
166
+ #### 2.2.0
167
+ * Updated dependencies for rspec and kaminari
168
+ * Make recover_report_history rake task a noop for no previously tracked BestBoyEvents
169
+ * Bugfix for report recovery rake task
170
+ * use appraisal for testing against different gemsets and Ruby versions
171
+
172
+ #### 2.1.3
173
+ * Compatible with Rails 4.1
174
+ * Loosened kaminari dependency requirements
175
+
176
+ #### 2.1.0
177
+ * Code cleanup - now compatible with RSpec 3 syntax
178
+ * Support a "dry-run" test mode
179
+ * Reduce public methods added by `BestBoy::Eventable` ([#4](https://github.com/Absolventa/best_boy/issues/4))
180
+ * Remove mass-assignments that could cause problems with the protected_attributes gem [#8](https://github.com/Absolventa/best_boy/issues/8)
181
+ * Do not expose mixed-in controller method ([#9](https://github.com/Absolventa/best_boy/issues/9)))
182
+ * Avoid potential name clashes for callbacks switch ([#10](https://github.com/Absolventa/best_boy/issues/10))
183
+
184
+
185
+
222
186
  Used gems and resources
223
187
  -----------------------
224
- * [Twitter Bootstrap](http://twitter.github.com/bootstrap/) in its version 2.0.4
188
+ * [Twitter Bootstrap](http://twitter.github.com/bootstrap/) in its version 3
225
189
  * [Stefan Petre](http://www.eyecon.ro/bootstrap-datepicker) for Datepicker in Twitter Bootstrap style
226
190
  * [Winston Teo Yong Wei](https://github.com/winston/google_visualr) Google_Visualr in its version 2.1.2
227
191
 
@@ -235,7 +199,7 @@ Contributors in alphabetic order
235
199
 
236
200
  Thanks
237
201
  ------
238
- We ♥ PRs – thanks to everyone contributing to this project. Big thanks to each contributor on Impressionist. This gem helped me ([cseydel](https://github.com/cseydel)) a long way to get here in modelling and creating a gem.
202
+ We ♥ PRs – thanks to everyone contributing to this project.
239
203
 
240
204
 
241
205
  See [LICENSE.txt](https://raw.github.com/Absolventa/best_boy/master/LICENSE.txt) for usage and licensing details.
@@ -10,4 +10,3 @@
10
10
  // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11
11
  // GO AFTER THE REQUIRES BELOW.
12
12
  //
13
- //= require best_boy/bootstrap_datepicker
@@ -0,0 +1,21 @@
1
+ body
2
+ padding-top: 60px
3
+
4
+ //reset pagination for kamiari
5
+ nav.pagination
6
+ text-align: center
7
+ span
8
+ float: left
9
+ border: 1px solid #ddd
10
+ padding: 6px 12px
11
+ position: relative
12
+ line-height: 24px
13
+ a
14
+ text-decoration: none
15
+ background-color: #fff
16
+ span.current
17
+ background-color: whiteSmoke
18
+ color: #999
19
+ cursor: default
20
+ span.gap
21
+ padding: 6px 12px
@@ -8,7 +8,5 @@
8
8
  * You're free to add application-wide styles to this file and they'll appear at the top of the
9
9
  * compiled file, but it's generally better to create a new file per style scope.
10
10
  *
11
- *= require_self
12
- *= require best_boy/bootstrap
13
- *= require best_boy/bootstrap_datepicker
11
+ *= require best_boy/base
14
12
  */
@@ -1,12 +1,12 @@
1
1
  module BestBoy
2
- class BestBoyEventsController < BestBoy.base_controller.constantize
2
+ class EventsController < BestBoy.base_controller.constantize
3
3
 
4
4
  before_action BestBoy.before_filter if BestBoy.before_filter.present?
5
5
 
6
6
  skip_before_filter BestBoy.skip_before_filter if BestBoy.skip_before_filter.present?
7
7
  skip_after_filter BestBoy.skip_after_filter if BestBoy.skip_after_filter.present?
8
8
 
9
- layout 'best_boy_backend'
9
+ layout 'best_boy/best_boy'
10
10
 
11
11
 
12
12
  helper BestBoy::BestBoyViewHelper
@@ -146,7 +146,7 @@ module BestBoy
146
146
  end
147
147
 
148
148
  def chart_for(data)
149
- @chart = GoogleVisualr::Interactive::AreaChart.new(data, { width: 900, height: 240, title: "" })
149
+ @chart = GoogleVisualr::Interactive::AreaChart.new(data, { width: 1100, height: 300, title: "" })
150
150
  end
151
151
 
152
152
  def row_values_for(day)
@@ -285,7 +285,7 @@ module BestBoy
285
285
  instance_variable_set(instance_var, value)
286
286
  end
287
287
 
288
- scope = BestBoyEvent
288
+ scope = BestBoy::Event
289
289
  scope = scope.where(owner_type: @owner_type) if @owner_type.present?
290
290
  scope = scope.where(event: @event) if @event.present?
291
291
  scope = scope.where(event_source: @event_source) if @event_source.present?
@@ -0,0 +1,29 @@
1
+ module BestBoy
2
+ class Event < ActiveRecord::Base
3
+
4
+ include BestBoy::ObeysTestMode
5
+
6
+ # db configuration
7
+ #
8
+ #
9
+
10
+ self.table_name = "best_boy_events"
11
+
12
+ # associations
13
+ #
14
+ #
15
+ belongs_to :owner, polymorphic: true
16
+
17
+ # validations
18
+ #
19
+ #
20
+ validates :event, presence: true
21
+
22
+ # scopes
23
+ #
24
+ #
25
+
26
+ scope :per_day, ->(date) { where(created_at: date.beginning_of_day..date.end_of_day ) }
27
+
28
+ end
29
+ end
@@ -0,0 +1,11 @@
1
+ <div class="row">
2
+ <div class="col-md-12">
3
+ <ul class="nav nav-tabs">
4
+ <% available_owner_types.each do |owner_type| %>
5
+ <li class="<%= (current_owner_type == owner_type) ? 'active' : nil %>">
6
+ <%= link_to owner_type, send("#{referrer}_events_path", owner_type: owner_type) %>
7
+ </li>
8
+ <% end %>
9
+ </ul>
10
+ </div>
11
+ </div>
@@ -0,0 +1,33 @@
1
+ <% content_for :javascripts do %>
2
+ <%= javascript_include_tag "https://www.google.com/jsapi" %>
3
+ <% end %>
4
+
5
+ <div class="row">
6
+ <div class="col-md-12">
7
+ <%= form_tag charts_events_path, method: :get, id: "chart-form" do %>
8
+ <div class="form-group">
9
+ <div class="col-md-3">
10
+ <%= select_tag :owner_type, options_for_select([["Owner", nil]] + available_owner_types, selected: params[:owner_type]), onchange: "submit();", class: "form-control" %>
11
+ </div>
12
+ <div class="col-md-3">
13
+ <%= select_tag :event, options_for_select([["Event", nil]] + available_events, selected: params[:event]), onchange: "submit();", class: "form-control" %>
14
+ </div>
15
+ <div class="col-md-3">
16
+ <%= select_tag :event_source, options_for_select([["Event Source", nil]] + available_event_sources, selected: params[:event_source]), onchange: "submit();", class: "form-control" %>
17
+ </div>
18
+ <div class="col-md-3">
19
+ <%= select_tag :time_interval, options_for_select([["Time Interval", nil], ["yearly", "year"], ["monthly", "month"], ["weekly", "week"]], selected: params[:time_interval]), onchange: "submit();", class: "form-control" %>
20
+ </div>
21
+ </div>
22
+ <% end %>
23
+ </div>
24
+ </div>
25
+
26
+ <div class="row">
27
+ <div class="col-md-12">
28
+ <div class="well">
29
+ <div id='chart'></div>
30
+ <%= render_chart(@chart, 'chart') %>
31
+ </div>
32
+ </div>
33
+ </div>
@@ -0,0 +1,98 @@
1
+ <div class="row">
2
+ <div class="col-md-12">
3
+ <div class="well">
4
+ <%= link_to "<< back to stats", stats_events_path(owner_type: current_owner_type) %>
5
+ </div>
6
+ </div>
7
+ </div>
8
+
9
+ <div class="row">
10
+ <div class="col-md-12">
11
+ <div class="well">
12
+ <h3>Detailed Statistics</h3>
13
+ <table class="table table-striped table-bordered">
14
+ <thead>
15
+ <tr>
16
+ <th>Source</th>
17
+ <th colspan="2">overall</th>
18
+ <th colspan="2">year</th>
19
+ <th colspan="2">month</th>
20
+ <th colspan="2">week</th>
21
+ <th colspan="2">day</th>
22
+ </tr>
23
+ </thead>
24
+ <% if available_event_sources.first.present? %>
25
+ <tbody>
26
+ <% @sourced_occurrences.keys.each do |source| %>
27
+ <tr>
28
+ <td><%= source %></td>
29
+ <% @sourced_occurrences[source].keys.reverse.each do |time_period| %>
30
+ <td><%= @sourced_occurrences[source][time_period] %></td>
31
+ <td><%= relative_occurrences(@sourced_occurrences[source], time_period) %></td>
32
+ <% end %>
33
+ </tr>
34
+ <% end %>
35
+ </tbody>
36
+ <% end %>
37
+ <tfoot>
38
+ <tr>
39
+ <th>All</th>
40
+ <% @occurrences[params[:event]].keys.reverse.each do |time_period| %>
41
+ <th><%= @occurrences[params[:event]][time_period] %></th>
42
+ <th><%= relative_occurrences(@occurrences[params[:event]], time_period)%></th>
43
+ <% end %>
44
+ </tr>
45
+ </tfoot>
46
+ </table>
47
+ </div>
48
+ </div>
49
+ </div>
50
+
51
+ <div class="row">
52
+ <div class="col-md-12">
53
+ <div class="well">
54
+ <div class="row">
55
+ <div class="col-md-10">
56
+ <h3>Detailed Statistics for <%= current_year %> per month</h3>
57
+ </div>
58
+ <div class="col-md-2">
59
+ <%= form_tag details_events_path, method: :get do %>
60
+ <%= hidden_field_tag :owner_type, current_owner_type %>
61
+ <%= hidden_field_tag :event, current_event %>
62
+ <%= select_tag :year, options_for_select(available_years, selected: current_year), onchange: "submit();", class: "form-control" %>
63
+ <% end %>
64
+ </div>
65
+ </div>
66
+ <table class="table table-striped table-bordered">
67
+ <thead>
68
+ <tr>
69
+ <th>Event Source</th>
70
+ <% month_name_array.each do |month| %>
71
+ <th><%= link_to month, monthly_details_events_path(owner_type: current_owner_type, event: current_event, month: month, year: current_year, time_interval: "month") %></th>
72
+ <% end %>
73
+ </tr>
74
+ </thead>
75
+ <tbody>
76
+ <% if available_event_sources? %>
77
+ <% @event_selected_year_occurrences.keys.reject { |k| k == "All" }.each do |source| %>
78
+ <tr>
79
+ <td><%= source %></td>
80
+ <% @event_selected_year_occurrences[source].keys.reject.each do |month| %>
81
+ <td><%= @event_selected_year_occurrences[source][month] %></td>
82
+ <% end %>
83
+ </tr>
84
+ <% end %>
85
+ <% end %>
86
+ </tbody>
87
+ <tfoot>
88
+ <tr>
89
+ <td><strong>All</strong></td>
90
+ <% @event_selected_year_occurrences["All"].keys.each do |month| %>
91
+ <td><%= @event_selected_year_occurrences["All"][month] %></td>
92
+ <% end %>
93
+ </tr>
94
+ </tfoot>
95
+ </table>
96
+ </div>
97
+ </div>
98
+ </div>