ifd_tools 0.1.0

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 (137) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +28 -0
  3. data/Rakefile +40 -0
  4. data/app/admin/emergency_messages.rb +33 -0
  5. data/app/admin/notifier_updates.rb +42 -0
  6. data/app/admin/software_updates.rb +42 -0
  7. data/app/admin/users.rb +48 -0
  8. data/app/assets/javascripts/ifd_tools/base.js +4 -0
  9. data/app/assets/javascripts/ifd_tools/fusion_charts.js +361 -0
  10. data/app/assets/stylesheets/ifd_tools/active_admin/_analytics.scss +32 -0
  11. data/app/assets/stylesheets/ifd_tools/active_admin/_cleanup.scss +15 -0
  12. data/app/assets/stylesheets/ifd_tools/active_admin/_footer.scss +87 -0
  13. data/app/assets/stylesheets/ifd_tools/active_admin/_square_admin_buttons.scss +27 -0
  14. data/app/assets/stylesheets/ifd_tools/base.scss +4 -0
  15. data/app/assets/swfs/FCF_Area2D.swf +0 -0
  16. data/app/assets/swfs/usa_map.swf +0 -0
  17. data/app/controllers/ifd_tools/application_controller.rb +4 -0
  18. data/app/helpers/ifd_tools/application_helper.rb +30 -0
  19. data/app/models/ifd_tools/emergency_message.rb +27 -0
  20. data/app/models/ifd_tools/notifier_update.rb +28 -0
  21. data/app/models/ifd_tools/software_update.rb +28 -0
  22. data/app/models/ifd_tools/tracking/application_event.rb +6 -0
  23. data/app/models/ifd_tools/tracking/event.rb +51 -0
  24. data/app/models/ifd_tools/tracking.rb +7 -0
  25. data/app/uploaders/software_uploader.rb +18 -0
  26. data/app/views/admin/customers/_trend.html.haml +7 -0
  27. data/app/views/admin/customers/_trend_info_sidebar.html.haml +11 -0
  28. data/app/views/admin/customers/demographic_data.builder +11 -0
  29. data/app/views/admin/customers/events_data.builder +6 -0
  30. data/app/views/admin/customers/filter_events.js.erb +6 -0
  31. data/app/views/admin/customers/trends.html.haml +11 -0
  32. data/app/views/admin/dashboard/_line_graph.html.haml +11 -0
  33. data/app/views/admin/dashboard/_usa_map.html.haml +2 -0
  34. data/app/views/admin/emergency_messages/_form.html.haml +6 -0
  35. data/app/views/admin/notifier_updates/_form.html.haml +9 -0
  36. data/app/views/admin/shared/_footer.html.haml +6 -0
  37. data/app/views/admin/software_updates/_form.html.haml +9 -0
  38. data/app/views/admin/users/_form.html.haml +9 -0
  39. data/app/views/api/emergency_messages.builder +12 -0
  40. data/app/views/api/notifier_updates.builder +15 -0
  41. data/app/views/api/software_updates.builder +15 -0
  42. data/app/views/api/track.builder +6 -0
  43. data/app/views/layouts/ifd_tools/application.html.erb +14 -0
  44. data/config/routes.rb +2 -0
  45. data/db/migrate/20121010183004_create_ifd_tools_emergency_messages.rb +11 -0
  46. data/db/migrate/20121011150939_create_ifd_tools_notifier_updates.rb +14 -0
  47. data/db/migrate/20121011151124_create_ifd_tools_software_updates.rb +14 -0
  48. data/db/migrate/20121011205911_devise_create_users.rb +57 -0
  49. data/db/migrate/20121012123505_create_customers.rb +52 -0
  50. data/db/migrate/20121012133303_create_ifd_tools_tracking_events.rb +14 -0
  51. data/lib/generators/ifd_tools/install/USAGE +5 -0
  52. data/lib/generators/ifd_tools/install/install_generator.rb +153 -0
  53. data/lib/generators/ifd_tools/install/templates/admin/customers.rb +108 -0
  54. data/lib/generators/ifd_tools/install/templates/admin/dashboard.rb +47 -0
  55. data/lib/generators/ifd_tools/install/templates/assets/active_admin.css.scss +7 -0
  56. data/lib/generators/ifd_tools/install/templates/assets/active_admin.js +2 -0
  57. data/lib/generators/ifd_tools/install/templates/assets/application.css.scss +46 -0
  58. data/lib/generators/ifd_tools/install/templates/assets/application.js +2 -0
  59. data/lib/generators/ifd_tools/install/templates/assets/ckeditor.js.coffee +13 -0
  60. data/lib/generators/ifd_tools/install/templates/capistrano/Capfile +5 -0
  61. data/lib/generators/ifd_tools/install/templates/capistrano/deploy/production.rb +2 -0
  62. data/lib/generators/ifd_tools/install/templates/capistrano/deploy/staging.rb +2 -0
  63. data/lib/generators/ifd_tools/install/templates/capistrano/deploy.rb +50 -0
  64. data/lib/generators/ifd_tools/install/templates/config/en.yml +17 -0
  65. data/lib/generators/ifd_tools/install/templates/config/ifd_tools.rb +4 -0
  66. data/lib/generators/ifd_tools/install/templates/config/schedule.rb.erb +28 -0
  67. data/lib/generators/ifd_tools/install/templates/controllers/api_controller.rb +8 -0
  68. data/lib/generators/ifd_tools/install/templates/controllers/application_controller.rb +19 -0
  69. data/lib/generators/ifd_tools/install/templates/controllers/customer_session_controller.rb +39 -0
  70. data/lib/generators/ifd_tools/install/templates/foreman/Procfile +2 -0
  71. data/lib/generators/ifd_tools/install/templates/layouts/application.html.haml +29 -0
  72. data/lib/generators/ifd_tools/install/templates/layouts/application_logged_out.html.haml +21 -0
  73. data/lib/generators/ifd_tools/install/templates/models/ability.rb +23 -0
  74. data/lib/generators/ifd_tools/install/templates/models/customer.rb +60 -0
  75. data/lib/generators/ifd_tools/install/templates/models/settings.rb +5 -0
  76. data/lib/generators/ifd_tools/install/templates/models/user.rb +31 -0
  77. data/lib/generators/ifd_tools/install/templates/settings/application.yml +16 -0
  78. data/lib/generators/ifd_tools/install/templates/views/customers/_form.html.haml +8 -0
  79. data/lib/ifd_tools/active_admin/base.rb +18 -0
  80. data/lib/ifd_tools/api_controller/emergency_messages.rb +9 -0
  81. data/lib/ifd_tools/api_controller/notifier_updates.rb +9 -0
  82. data/lib/ifd_tools/api_controller/software_updates.rb +9 -0
  83. data/lib/ifd_tools/api_controller/tracking.rb +44 -0
  84. data/lib/ifd_tools/api_controller_extensions.rb +18 -0
  85. data/lib/ifd_tools/configure.rb +27 -0
  86. data/lib/ifd_tools/date_time_additions.rb +11 -0
  87. data/lib/ifd_tools/engine.rb +17 -0
  88. data/lib/ifd_tools/states.rb +59 -0
  89. data/lib/ifd_tools/tracking/customer_tracking.rb +143 -0
  90. data/lib/ifd_tools/tracking/trackable.rb +28 -0
  91. data/lib/ifd_tools/validations/phone.rb +17 -0
  92. data/lib/ifd_tools/version.rb +3 -0
  93. data/lib/ifd_tools.rb +26 -0
  94. data/lib/tasks/ifd_tools_tasks.rake +2 -0
  95. data/test/dummy/README.rdoc +261 -0
  96. data/test/dummy/Rakefile +7 -0
  97. data/test/dummy/app/assets/javascripts/application.js +15 -0
  98. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  99. data/test/dummy/app/controllers/application_controller.rb +3 -0
  100. data/test/dummy/app/helpers/application_helper.rb +2 -0
  101. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  102. data/test/dummy/config/application.rb +59 -0
  103. data/test/dummy/config/boot.rb +10 -0
  104. data/test/dummy/config/database.yml +25 -0
  105. data/test/dummy/config/environment.rb +5 -0
  106. data/test/dummy/config/environments/development.rb +37 -0
  107. data/test/dummy/config/environments/production.rb +67 -0
  108. data/test/dummy/config/environments/test.rb +37 -0
  109. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  110. data/test/dummy/config/initializers/inflections.rb +15 -0
  111. data/test/dummy/config/initializers/mime_types.rb +5 -0
  112. data/test/dummy/config/initializers/secret_token.rb +7 -0
  113. data/test/dummy/config/initializers/session_store.rb +8 -0
  114. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  115. data/test/dummy/config/locales/en.yml +5 -0
  116. data/test/dummy/config/routes.rb +4 -0
  117. data/test/dummy/config.ru +4 -0
  118. data/test/dummy/db/development.sqlite3 +0 -0
  119. data/test/dummy/db/schema.rb +24 -0
  120. data/test/dummy/log/development.log +15 -0
  121. data/test/dummy/public/404.html +26 -0
  122. data/test/dummy/public/422.html +26 -0
  123. data/test/dummy/public/500.html +25 -0
  124. data/test/dummy/public/favicon.ico +0 -0
  125. data/test/dummy/script/rails +6 -0
  126. data/test/fixtures/ifd_tools/emergency_messages.yml +11 -0
  127. data/test/fixtures/ifd_tools/notifier_updates.yml +17 -0
  128. data/test/fixtures/ifd_tools/software_updates.yml +17 -0
  129. data/test/fixtures/ifd_tools/tracking/events.yml +17 -0
  130. data/test/ifd_tools_test.rb +7 -0
  131. data/test/integration/navigation_test.rb +10 -0
  132. data/test/test_helper.rb +15 -0
  133. data/test/unit/ifd_tools/emergency_message_test.rb +9 -0
  134. data/test/unit/ifd_tools/notifier_update_test.rb +9 -0
  135. data/test/unit/ifd_tools/software_update_test.rb +9 -0
  136. data/test/unit/ifd_tools/tracking/event_test.rb +9 -0
  137. metadata +464 -0
@@ -0,0 +1,29 @@
1
+ %html
2
+ %head
3
+ %title= Settings.app_name
4
+ = stylesheet_link_tag "application", media: "all"
5
+ = javascript_include_tag "application"
6
+ = favicon_link_tag
7
+ = csrf_meta_tags
8
+
9
+ %body(class="active_admin logged_in #{params[:controller].gsub('/', '_')} #{params[:action]}")
10
+
11
+ #wrapper
12
+ #header.header
13
+
14
+ %h1#site_title.site_title= @page_title || Settings.app_header_name
15
+ %p#utility_nav.header-item
16
+ /= link_to "Sign Out", destroy_customer_session_path, method: :delete, title: "Sign Out"
17
+
18
+ .flashes
19
+ - flash.each do |type, message|
20
+ %div(class="flash flash_#{type}")= message
21
+
22
+ #active_admin_content.without_sidebar
23
+ #main_content_wrapper
24
+ = yield
25
+ .clearBoth
26
+
27
+ #footer
28
+ #site_footer
29
+ = yield :footer
@@ -0,0 +1,21 @@
1
+ %html
2
+ %head
3
+ %title= Settings.app_name
4
+ = stylesheet_link_tag "application", media: "all"
5
+ = javascript_include_tag "application"
6
+ = csrf_meta_tags
7
+
8
+ %body(class="logged_out #{params[:controller].gsub('/', '_')} #{params[:action]}")
9
+
10
+ #wrapper
11
+ #header.header
12
+ %h1#site_title= @page_title || Settings.app_header_name
13
+ #content_wrapper
14
+ - flash.each do |type, message|
15
+ %div(class="flash flash_#{type}")= message
16
+
17
+ #active_admin_content
18
+ = yield
19
+
20
+ #footer
21
+ = yield :footer
@@ -0,0 +1,23 @@
1
+ class Ability
2
+ include CanCan::Ability
3
+
4
+ def initialize(user)
5
+
6
+ user ||= User.new
7
+
8
+ can :manage, :all
9
+ cannot [:create, :new], Customer
10
+
11
+ unless user.super_admin?
12
+
13
+ # Only manage regular accounts
14
+ cannot :manage, User
15
+ can :manage, User, role: %w(admin)
16
+
17
+ # Cannot manage some other sensitive items
18
+ cannot :manage, [IfdTools::SoftwareUpdate, IfdTools::EmergencyMessage, IfdTools::NotifierUpdate]
19
+
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,60 @@
1
+ class Customer < ActiveRecord::Base
2
+
3
+ Statuses = %w(active banned pending)
4
+
5
+ devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable, :token_authenticatable, :confirmable
6
+
7
+ has_many :tracking_events, :class_name => 'IfdTools::Tracking::Event', dependent: :destroy
8
+
9
+ # Setup accessible (or protected) attributes for your model
10
+ attr_accessible :email, :password, :password_confirmation, :remember_me, :first_name, :last_name, :phone, :state, :platform
11
+
12
+ validates :first_name, :last_name, :email, :state, presence: true
13
+ validates_phone :phone, presence: true
14
+
15
+ default_scope order("lower(first_name) asc, lower(last_name) asc")
16
+
17
+ Statuses.each do |s|
18
+ scope s.to_sym, where(status: s)
19
+ define_method("#{s}?") { status == s }
20
+ end
21
+
22
+ scope :unconfirmed, where(confirmed_at: nil)
23
+ scope :top_users, includes(:tracking_events).group("ifd_tools_tracking_events.customer_id").reorder("count(ifd_tools_tracking_events.customer_id) desc, lower(first_name) asc, lower(last_name) asc")
24
+
25
+ before_save :ensure_authentication_token
26
+ before_save :sanitize_phone
27
+
28
+ acts_as_url :full_name, limit: 100
29
+
30
+ def full_name
31
+ "#{first_name} #{last_name}"
32
+ end
33
+
34
+ def display_name
35
+ full_name
36
+ end
37
+
38
+ def to_param
39
+ url
40
+ end
41
+
42
+ def activate!
43
+ update_attribute :status, "active"
44
+ end
45
+
46
+ def deactivate!
47
+ update_attribute :status, "banned"
48
+ end
49
+
50
+ def active?
51
+ status == "active"
52
+ end
53
+
54
+ private
55
+
56
+ def sanitize_phone
57
+ self.phone = phone.gsub(/[^0-9]*/, '')
58
+ end
59
+
60
+ end
@@ -0,0 +1,5 @@
1
+ class Settings < Settingslogic
2
+ source "#{Rails.root}/config/application.yml"
3
+ namespace Rails.env
4
+ load!
5
+ end
@@ -0,0 +1,31 @@
1
+ class User < ActiveRecord::Base
2
+
3
+ Roles = %w(admin super_admin)
4
+
5
+ devise :database_authenticatable, :recoverable, :rememberable, :trackable, :validatable
6
+ attr_accessible :email, :password, :password_confirmation, :remember_me, :first_name, :last_name, :time_zone, :role
7
+
8
+ validates :first_name, :last_name, presence: true
9
+
10
+ default_scope order("lower(first_name) asc, lower(last_name) asc")
11
+
12
+ after_create { |admin| admin.delay.send_reset_password_instructions }
13
+
14
+ def full_name
15
+ "#{first_name} #{last_name}"
16
+ end
17
+
18
+ def display_name
19
+ full_name
20
+ end
21
+
22
+ Roles.each do |r|
23
+ define_method("#{r}?") { role == r }
24
+ scope r.to_sym, where(role: r)
25
+ end
26
+
27
+ def password_required?
28
+ new_record? ? false : super
29
+ end
30
+
31
+ end
@@ -0,0 +1,16 @@
1
+ defaults: &defaults
2
+ notifications_email: "notifications@domain.com"
3
+ app_name: "Name of CMS"
4
+ app_header_name: "Name of App Header"
5
+
6
+ development:
7
+ <<: *defaults
8
+
9
+ test:
10
+ <<: *defaults
11
+
12
+ staging:
13
+ <<: *defaults
14
+
15
+ production:
16
+ <<: *defaults
@@ -0,0 +1,8 @@
1
+ = semantic_form_for [:admin, @customer] do |f|
2
+ = f.inputs "Customer Information" do
3
+ = f.input :first_name, label: "First Name"
4
+ = f.input :last_name, label: "Last Name"
5
+ = f.input :email
6
+ = f.input :phone, input_html: { value: phone_number(@customer.phone) }
7
+ = f.input :state, as: :select, collection: IfdTools::States::all.invert
8
+ = f.buttons
@@ -0,0 +1,18 @@
1
+ module ActiveAdmin
2
+ module Views
3
+ module Pages
4
+ class Base# < Arbre::HTML::Document
5
+
6
+ private
7
+
8
+ # Renders the content for the footer
9
+ def build_footer
10
+ div :id => "footer" do
11
+ text_node(render 'admin/shared/footer')
12
+ end
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ module IfdTools
2
+ module ApiController
3
+ module EmergencyMessages
4
+ def emergency_messages
5
+ @messages = IfdTools::EmergencyMessage.active.first
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module IfdTools
2
+ module ApiController
3
+ module NotifierUpdates
4
+ def notifier_updates
5
+ @notifier_update = NotifierUpdate.current.first
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module IfdTools
2
+ module ApiController
3
+ module SoftwareUpdates
4
+ def software_updates
5
+ @software_update = SoftwareUpdate.current.first
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,44 @@
1
+ module IfdTools
2
+ module ApiController
3
+ module Tracking
4
+
5
+ # Used to record events from the application
6
+ #
7
+ # - trackable_type: ("application_event", "product_event") should be the last part of a model name, ie "IfdTools::Tracking::ProductEvent" => "product_event"
8
+ # - trackable_id: integer pk (null if trackable_type == "application")
9
+ # #
10
+ def track
11
+
12
+ begin
13
+
14
+ unless params[:type].present? && params[:id].present?
15
+ @error = "Missing 'type' or 'id' parameter"
16
+ render status: :unprocessable_entity and return
17
+ end
18
+
19
+ case params[:type]
20
+ when "application_event"
21
+ @event = IfdTools::Tracking::ApplicationEvent.new
22
+
23
+ else
24
+ @event = "ifd_tools/tracking/#{params[:type]}".camelize.constantize.new
25
+ @event.assign_trackable_item_by_id(params[:id])
26
+
27
+ end
28
+
29
+ unless @event.nil?
30
+ @event.ip_address = request.remote_ip
31
+ @event.customer = current_customer
32
+ @event.platform = IfdTools::Tracking::Event.platform_for_request(request)
33
+ @event.save!
34
+ end
35
+
36
+ rescue Exception => e
37
+ @error = e.message
38
+ render status: :unprocessable_entity
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,18 @@
1
+ require 'ifd_tools/api_controller/emergency_messages'
2
+ require 'ifd_tools/api_controller/software_updates'
3
+ require 'ifd_tools/api_controller/notifier_updates'
4
+ require 'ifd_tools/api_controller/tracking'
5
+
6
+ module IfdTools
7
+ module ApiControllerExtensions
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ include IfdTools::ApiController::EmergencyMessages
12
+ include IfdTools::ApiController::SoftwareUpdates
13
+ include IfdTools::ApiController::NotifierUpdates
14
+ include IfdTools::ApiController::Tracking
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+ module IfdTools
2
+ class Configure
3
+ class << self
4
+
5
+ def dashboard_graph_color=(c)
6
+ @@dashboard_graph_color = c
7
+ end
8
+
9
+ def dashboard_graph_color
10
+ @@dashboard_graph_color ||= "AFD8F8"
11
+ end
12
+
13
+ def dashboard_graph_main_color=(c)
14
+ @@dashboard_graph_main_color = c
15
+ end
16
+
17
+ def dashboard_graph_main_color
18
+ @@dashboard_graph_main_color ||= "114B78"
19
+ end
20
+
21
+ def setup(&block)
22
+ block.call(self)
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,11 @@
1
+ class Time
2
+ def humanize
3
+ strftime "%b %d, %Y %I:%M%p"
4
+ end
5
+ end
6
+
7
+ class Date
8
+ def humanize
9
+ strftime "%b %d, %Y"
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+ module IfdTools
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace IfdTools
4
+
5
+ initializer "ifd_tools.load_static_assets" do |app|
6
+ app.middleware.use ::ActionDispatch::Static, "#{root}/public"
7
+ end
8
+
9
+ initializer "ifd_tools.active_admin" do |app|
10
+ ActiveAdmin::Event.subscribe ActiveAdmin::Application::BeforeLoadEvent do |app|
11
+ require 'ifd_tools/tracking/customer_tracking'
12
+ app.load_paths << File.expand_path( File.dirname(__FILE__) + "../../../app/admin" )
13
+ end
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,59 @@
1
+ module IfdTools
2
+ module States
3
+ def self.all
4
+ state_abbr = {
5
+ 'AL' => 'Alabama',
6
+ 'AK' => 'Alaska',
7
+ 'AZ' => 'Arizona',
8
+ 'AR' => 'Arkansas',
9
+ 'CA' => 'California',
10
+ 'CO' => 'Colorado',
11
+ 'CT' => 'Connecticut',
12
+ 'DE' => 'Delaware',
13
+ 'DC' => 'District of Columbia',
14
+ 'FL' => 'Florida',
15
+ 'GA' => 'Georgia',
16
+ 'HI' => 'Hawaii',
17
+ 'ID' => 'Idaho',
18
+ 'IL' => 'Illinois',
19
+ 'IN' => 'Indiana',
20
+ 'IA' => 'Iowa',
21
+ 'KS' => 'Kansas',
22
+ 'KY' => 'Kentucky',
23
+ 'LA' => 'Louisiana',
24
+ 'ME' => 'Maine',
25
+ 'MD' => 'Maryland',
26
+ 'MA' => 'Massachusetts',
27
+ 'MI' => 'Michigan',
28
+ 'MN' => 'Minnesota',
29
+ 'MS' => 'Mississippi',
30
+ 'MO' => 'Missouri',
31
+ 'MT' => 'Montana',
32
+ 'NE' => 'Nebraska',
33
+ 'NV' => 'Nevada',
34
+ 'NH' => 'New Hampshire',
35
+ 'NJ' => 'New Jersey',
36
+ 'NM' => 'New Mexico',
37
+ 'NY' => 'New York',
38
+ 'NC' => 'North Carolina',
39
+ 'ND' => 'North Dakota',
40
+ 'OH' => 'Ohio',
41
+ 'OK' => 'Oklahoma',
42
+ 'OR' => 'Oregon',
43
+ 'PA' => 'Pennsylvania',
44
+ 'RI' => 'Rhode Island',
45
+ 'SC' => 'South Carolina',
46
+ 'SD' => 'South Dakota',
47
+ 'TN' => 'Tennessee',
48
+ 'TX' => 'Texas',
49
+ 'UT' => 'Utah',
50
+ 'VT' => 'Vermont',
51
+ 'VA' => 'Virginia',
52
+ 'WA' => 'Washington',
53
+ 'WV' => 'West Virginia',
54
+ 'WI' => 'Wisconsin',
55
+ 'WY' => 'Wyoming'
56
+ }
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,143 @@
1
+ module IfdTools
2
+ module Tracking
3
+ module CustomerTracking
4
+
5
+ def self.included(dsl)
6
+
7
+ # Action item to view trends of the resource
8
+ dsl.action_item only: [:show, :edit] do
9
+ link_to "Trends", [:trends, :admin, resource]
10
+ end
11
+
12
+ # Actual controller action for viewing the trends
13
+ dsl.send(:member_action, :trends) do
14
+ @customer = Customer.find_by_url! params[:id]
15
+ @trends = IfdTools::Tracking::Event.where(customer_id: @customer.id).limit(75)
16
+ @registration_date = @customer.created_at
17
+ @application_launches = IfdTools::Tracking::ApplicationEvent.where(customer_id: @customer.id).count
18
+ end
19
+
20
+ # Sidebar when viewing trends for resource
21
+ dsl.sidebar :trend_info, only: :trends
22
+
23
+ # Provides XML for the USA map
24
+ dsl.send(:collection_action, :demographic_data) do
25
+
26
+ @total_activity = IfdTools::Tracking::Event.count
27
+ @activity = []
28
+
29
+ db_activity_per_state = IfdTools::Tracking::Event.includes(:customer).group("customers.state").count
30
+ users_per_state = Customer.group(:state).count
31
+
32
+ IfdTools::States::all.each do |state, long_name|
33
+ @activity << OpenStruct.new(name: long_name, activity: db_activity_per_state[state] || 0.00, users: users_per_state[state] || 0)
34
+ end
35
+
36
+ end
37
+
38
+ dsl.send(:collection_action, :filter_events, method: :post) do
39
+
40
+ cookies[:filter_events] = params[:q].to_yaml
41
+ respond_to do |format|
42
+ format.js
43
+ format.html { redirect_to admin_dashboard_url }
44
+ end
45
+
46
+ end
47
+
48
+ # Provides XML for FusionCharts content graph on dashboard
49
+ dsl.send(:collection_action, :events_data) do
50
+
51
+ filters = YAML.load(cookies[:filter_events]).symbolize_keys rescue {}
52
+ @color = IfdTools::Configure.dashboard_graph_color
53
+ @events = IfdTools::Tracking::Event.scoped
54
+
55
+ unless filters.empty?
56
+
57
+ @events = IfdTools::Tracking::Event.search(filters)
58
+ if filters[:timestamp_gte].present? and filters[:timestamp_lte].present?
59
+ @time_range = "Between #{filters[:timestamp_gte]} and #{filters[:timestamp_lte]}"
60
+ elsif filters[:timestamp_gte].present?
61
+ @time_range = "Since #{filters[:timestamp_gte]}"
62
+ elsif filters[:timestamp_lte].present?
63
+ @time_range = "Before #{filters[:timestamp_lte]}"
64
+ end
65
+
66
+ @filter_type = filters[:type_eq].gsub("IfdTools::Tracking::", "").titleize rescue nil
67
+ @filter_type = "Everything" if @filter_type.blank?
68
+
69
+ @caption = "Activity #{@time_range || 'for All Time'}"
70
+ @subcaption = "Type: #{@filter_type}"
71
+
72
+ @subcaption << " (Mac)" if filters[:platform_eq] == "mac"
73
+ @subcaption << " (PC)" if filters[:platform_eq] == "pc"
74
+
75
+ end
76
+
77
+ # Grab the date/value pairs from the db
78
+ @events = @events.group("date(timestamp)")
79
+
80
+ # Depending on how many records exist, want to narrow that down a good bit
81
+ distribution = @events.count
82
+ first_date = distribution.keys.first.to_date
83
+ last_date = distribution.keys.last.to_date
84
+ num_days_in_time_span = (first_date..last_date).count rescue 0
85
+
86
+ grouping = :days
87
+ if num_days_in_time_span > 450 # ~ 15 months
88
+ @events = @events.group_by { |e| e.timestamp.beginning_of_year.to_date }
89
+ grouping = :years
90
+ elsif num_days_in_time_span > 175 # 7 weeks
91
+ @events = @events.group_by { |e| e.timestamp.beginning_of_month.to_date }
92
+ grouping = :months
93
+ elsif num_days_in_time_span > 25 # 25 days
94
+ @events = @events.group_by { |e| e.timestamp.beginning_of_week.to_date }
95
+ grouping = :weeks
96
+ else
97
+ @events = @events.count
98
+ end
99
+
100
+ # End up with Hash of date => count pairs
101
+ unless grouping == :days
102
+ @events.delete_if { |k, v| v.nil? }.map { |date, arr| @events[date] = arr.count }
103
+ end
104
+
105
+ # Start/end dates might have changed
106
+ first_date = @events.keys.first.to_date
107
+ last_date = @events.keys.last.to_date
108
+
109
+ date_step =
110
+ case grouping
111
+ when :years
112
+ 1.year
113
+ when :months
114
+ 1.month
115
+ when :weeks
116
+ 1.week
117
+ else
118
+ 1.day
119
+ end
120
+
121
+ # Was using a gorgeous "first_date.step(last_date, 1.month).to_a" syntax, but that didn't work in Ruby 1.9.3 for some reason
122
+ event_keys = []
123
+ unless first_date.nil?
124
+ curr_date = first_date.dup
125
+ until curr_date > last_date do
126
+ event_keys << curr_date.to_s
127
+ curr_date += date_step
128
+ end
129
+ end
130
+
131
+ # End up with just { date => FixNum } pairs, with zero values for dates that weren't in the db
132
+ @events = event_keys.inject({}) { |k, v| k[v] = 0; k }.merge(@events)
133
+
134
+ # Only wanted to use this for one request only
135
+ cookies.delete(:filter_events)
136
+
137
+ end
138
+
139
+ end
140
+
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,28 @@
1
+ module IfdTools
2
+ module Trackable
3
+
4
+ def self.included(base)
5
+ base.class_eval do
6
+ has_many :tracking_events, :class_name => 'IfdTools::Tracking::Event', foreign_key: :trackable_id, dependent: :destroy
7
+ end
8
+ end
9
+
10
+ def trackable_title
11
+ name rescue title
12
+ end
13
+
14
+ def trackable_type
15
+ self.class.name.titleize
16
+ end
17
+
18
+ # Override if you might want to link to something else
19
+ def trackable_resource
20
+ self
21
+ end
22
+
23
+ def trackable_activity
24
+ tracking_events.count
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ module IfdTools
2
+ module Validations
3
+
4
+ module Phone
5
+ def validates_phone(*args)
6
+ options = { :format => { :with => /^\(?\d{3}\)?\s*[-|.]?\s*\d{3}\s*[-|.]?\d{4}\s*$/, :message => "'%{value}' is not a valid phone number" } }
7
+ if !args.empty? and args.last.is_a?(Hash)
8
+ options.merge! args.pop
9
+ end
10
+ args.each { |attribute| validates attribute.to_sym, options }
11
+ end
12
+ end
13
+
14
+ end
15
+ end
16
+
17
+ ActiveRecord::Base.send(:extend, IfdTools::Validations::Phone)
@@ -0,0 +1,3 @@
1
+ module IfdTools
2
+ VERSION = "0.1.0"
3
+ end
data/lib/ifd_tools.rb ADDED
@@ -0,0 +1,26 @@
1
+ require 'carrierwave'
2
+ require 'cancan'
3
+ require 'active_admin'
4
+ require 'delayed_job_active_record'
5
+ require 'devise-async'
6
+ require 'cocoon'
7
+ require 'compass-rails'
8
+ require 'ckeditor-rails'
9
+ require 'stringex'
10
+ require 'daemons'
11
+ require 'haml'
12
+ require 'swfobject-rails'
13
+
14
+ require "ifd_tools/engine"
15
+ require 'ifd_tools/date_time_additions'
16
+ require 'ifd_tools/active_admin/base'
17
+ require 'ifd_tools/validations/phone'
18
+
19
+ module IfdTools
20
+
21
+ autoload :ApiControllerExtensions, 'ifd_tools/api_controller_extensions'
22
+ autoload :Configure, 'ifd_tools/configure'
23
+ autoload :States, 'ifd_tools/states'
24
+ autoload :Trackable, 'ifd_tools/tracking/trackable'
25
+
26
+ end
@@ -0,0 +1,2 @@
1
+ namespace :ifd_tools do
2
+ end