fat_free_crm 0.11.1 → 0.11.2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of fat_free_crm might be problematic. Click here for more details.

Files changed (179) hide show
  1. data/Gemfile +30 -12
  2. data/Gemfile.lock +131 -119
  3. data/Procfile +1 -1
  4. data/README.md +1 -1
  5. data/app/assets/images/notifications.png +0 -0
  6. data/app/assets/javascripts/application.js.erb +3 -0
  7. data/app/assets/javascripts/crm_textarea_autocomplete.js +44 -0
  8. data/app/assets/stylesheets/application.css.erb +2 -0
  9. data/app/assets/stylesheets/common.scss +7 -11
  10. data/app/assets/stylesheets/textarea_autocomplete.scss +42 -0
  11. data/app/controllers/admin/application_controller.rb +5 -5
  12. data/app/controllers/admin/field_groups_controller.rb +11 -51
  13. data/app/controllers/admin/fields_controller.rb +13 -59
  14. data/app/controllers/admin/plugins_controller.rb +1 -4
  15. data/app/controllers/admin/settings_controller.rb +0 -4
  16. data/app/controllers/admin/tags_controller.rb +11 -66
  17. data/app/controllers/admin/users_controller.rb +20 -83
  18. data/app/controllers/application_controller.rb +83 -69
  19. data/app/controllers/comments_controller.rb +12 -29
  20. data/app/controllers/emails_controller.rb +1 -5
  21. data/app/controllers/entities/accounts_controller.rb +13 -32
  22. data/app/controllers/entities/campaigns_controller.rb +17 -32
  23. data/app/controllers/entities/contacts_controller.rb +20 -38
  24. data/app/controllers/entities/leads_controller.rb +33 -55
  25. data/app/controllers/entities/opportunities_controller.rb +26 -42
  26. data/app/controllers/entities_controller.rb +92 -83
  27. data/app/controllers/home_controller.rb +1 -10
  28. data/app/controllers/lists_controller.rb +1 -4
  29. data/app/controllers/{entities/tasks_controller.rb → tasks_controller.rb} +21 -32
  30. data/app/controllers/users_controller.rb +6 -5
  31. data/app/helpers/accounts_helper.rb +32 -9
  32. data/app/helpers/application_helper.rb +15 -1
  33. data/app/helpers/campaigns_helper.rb +1 -1
  34. data/app/helpers/comments_helper.rb +11 -1
  35. data/app/helpers/leads_helper.rb +1 -1
  36. data/app/helpers/opportunities_helper.rb +1 -1
  37. data/app/{models/mailers/notifier.rb → mailers/dropbox_mailer.rb} +5 -16
  38. data/app/mailers/subscription_mailer.rb +37 -0
  39. data/{lib/tasks/dropbox.rake → app/mailers/user_mailer.rb} +11 -13
  40. data/app/models/entities/account.rb +3 -1
  41. data/app/models/entities/campaign.rb +3 -1
  42. data/app/models/entities/contact.rb +3 -1
  43. data/app/models/entities/lead.rb +6 -5
  44. data/app/models/entities/opportunity.rb +3 -1
  45. data/app/models/fields/field.rb +1 -1
  46. data/app/models/polymorphic/comment.rb +34 -0
  47. data/app/models/{entities → polymorphic}/task.rb +16 -3
  48. data/app/models/setting.rb +15 -15
  49. data/app/models/users/ability.rb +12 -5
  50. data/app/models/users/user.rb +7 -2
  51. data/app/views/accounts/index.html.haml +1 -1
  52. data/app/views/accounts/index.js.rjs +1 -1
  53. data/app/views/admin/plugins/index.html.haml +1 -7
  54. data/app/views/{shared/auto_complete.html.haml → application/_auto_complete.html.haml} +0 -0
  55. data/app/views/{shared → application}/index.atom.builder +1 -1
  56. data/app/views/{shared → application}/index.rss.builder +1 -1
  57. data/app/views/campaigns/index.html.haml +1 -1
  58. data/app/views/campaigns/index.js.rjs +1 -1
  59. data/app/views/comments/_new.html.haml +6 -0
  60. data/app/views/comments/_subscription_links.html.haml +13 -0
  61. data/app/views/comments/new.js.rjs +2 -0
  62. data/app/views/contacts/_top_section.html.haml +3 -13
  63. data/app/views/contacts/index.html.haml +1 -1
  64. data/app/views/contacts/index.js.rjs +1 -1
  65. data/app/views/{notifier/dropbox_ack_notification.html.haml → dropbox_mailer/dropbox_notification.html.haml} +2 -2
  66. data/app/views/{shared → entities}/attach.js.rjs +1 -1
  67. data/app/views/entities/contacts.js.rjs +1 -1
  68. data/app/views/{shared/discard.rjs → entities/discard.js.rjs} +0 -0
  69. data/app/views/entities/leads.js.rjs +1 -1
  70. data/app/views/entities/opportunities.js.rjs +1 -1
  71. data/app/views/entities/subscription_update.js.rjs +4 -0
  72. data/app/views/entities/versions.js.rjs +1 -1
  73. data/app/views/layouts/_footer.html.haml +1 -1
  74. data/app/views/layouts/application.html.haml +3 -0
  75. data/app/views/leads/_contact.html.haml +1 -0
  76. data/app/views/leads/index.html.haml +1 -1
  77. data/app/views/leads/index.js.rjs +1 -1
  78. data/app/views/opportunities/_top_section.html.haml +4 -14
  79. data/app/views/opportunities/index.html.haml +1 -1
  80. data/app/views/opportunities/index.js.rjs +1 -1
  81. data/app/views/subscription_mailer/comment_notification.text.erb +7 -0
  82. data/app/views/{notifier → user_mailer}/password_reset_instructions.html.haml +0 -0
  83. data/config/application.rb +3 -1
  84. data/config/environments/development.rb +1 -1
  85. data/config/environments/test.rb +3 -0
  86. data/config/initializers/action_mailer.rb +8 -5
  87. data/config/initializers/cancan.rb +151 -0
  88. data/config/initializers/constants.rb +1 -0
  89. data/config/initializers/locale.rb +20 -0
  90. data/config/initializers/paper_trail.rb +4 -5
  91. data/config/initializers/relative_url_root.rb +0 -1
  92. data/config/initializers/squeel.rb +5 -0
  93. data/config/locales/cz_fat_free_crm.yml +3 -3
  94. data/config/locales/de.yml +2 -2
  95. data/config/locales/de_fat_free_crm.yml +651 -596
  96. data/config/locales/en-GB_fat_free_crm.yml +3 -3
  97. data/config/locales/en-US_fat_free_crm.yml +13 -3
  98. data/config/locales/es_fat_free_crm.yml +3 -3
  99. data/config/locales/fr-CA_fat_free_crm.yml +3 -3
  100. data/config/locales/fr_fat_free_crm.yml +3 -3
  101. data/config/locales/it_fat_free_crm.yml +3 -3
  102. data/config/locales/pl_fat_free_crm.yml +3 -3
  103. data/config/locales/pt-BR_fat_free_crm.yml +3 -3
  104. data/config/locales/ru_fat_free_crm.yml +3 -3
  105. data/config/locales/sv-SE_fat_free_crm.yml +3 -3
  106. data/config/locales/th_fat_free_crm.yml +3 -3
  107. data/config/routes.rb +10 -0
  108. data/config/settings.default.yml +29 -10
  109. data/config/unicorn.rb +4 -0
  110. data/db/migrate/20111201030535_add_field_groups_klass_name.rb +3 -1
  111. data/db/migrate/20120314080441_add_subscribed_users_to_entities.rb +23 -0
  112. data/db/migrate/20120405080727_change_subscribed_users_to_set.rb +24 -0
  113. data/db/migrate/20120405080742_change_further_subscribed_users_to_set.rb +27 -0
  114. data/db/migrate/20120413034923_add_index_on_versions_item_type.rb +5 -0
  115. data/db/schema.rb +109 -126
  116. data/fat_free_crm.gemspec +12 -18
  117. data/lib/fat_free_crm.rb +0 -1
  118. data/lib/fat_free_crm/core_ext/array.rb +1 -0
  119. data/lib/fat_free_crm/gem_dependencies.rb +1 -0
  120. data/lib/fat_free_crm/mail_processor/base.rb +226 -0
  121. data/lib/fat_free_crm/mail_processor/comment_replies.rb +86 -0
  122. data/lib/fat_free_crm/mail_processor/dropbox.rb +288 -0
  123. data/lib/fat_free_crm/permissions.rb +6 -19
  124. data/lib/fat_free_crm/renderers.rb +0 -8
  125. data/lib/fat_free_crm/tabs.rb +1 -1
  126. data/lib/fat_free_crm/version.rb +1 -1
  127. data/lib/plugins/country_select/lib/country_select.rb +2 -2
  128. data/lib/tasks/mail_processing.rake +60 -0
  129. data/spec/controllers/admin/users_controller_spec.rb +0 -2
  130. data/spec/controllers/{accounts_controller_spec.rb → entities/accounts_controller_spec.rb} +7 -9
  131. data/spec/controllers/{campaigns_controller_spec.rb → entities/campaigns_controller_spec.rb} +7 -7
  132. data/spec/controllers/{contacts_controller_spec.rb → entities/contacts_controller_spec.rb} +5 -9
  133. data/spec/controllers/{leads_controller_spec.rb → entities/leads_controller_spec.rb} +7 -9
  134. data/spec/controllers/{opportunities_controller_spec.rb → entities/opportunities_controller_spec.rb} +8 -15
  135. data/spec/controllers/tasks_controller_spec.rb +1 -5
  136. data/spec/controllers/users_controller_spec.rb +5 -9
  137. data/spec/factories/subscription_factories.rb +6 -0
  138. data/spec/lib/mail_processor/base_spec.rb +164 -0
  139. data/spec/lib/mail_processor/comment_replies_spec.rb +63 -0
  140. data/spec/lib/{dropbox_spec.rb → mail_processor/dropbox_spec.rb} +73 -181
  141. data/spec/lib/mail_processor/sample_emails/dropbox.rb +167 -0
  142. data/spec/mailers/subscription_mailer_spec.rb +17 -0
  143. data/spec/models/{base → entities}/account_contact_spec.rb +0 -0
  144. data/spec/models/{base → entities}/account_opportunity_spec.rb +0 -0
  145. data/spec/models/{base → entities}/account_spec.rb +4 -0
  146. data/spec/models/{base → entities}/campaign_spec.rb +4 -0
  147. data/spec/models/{base → entities}/contact_opportunity_spec.rb +0 -0
  148. data/spec/models/{base → entities}/contact_spec.rb +4 -0
  149. data/spec/models/{base → entities}/lead_spec.rb +4 -0
  150. data/spec/models/{base → entities}/opportunity_spec.rb +4 -0
  151. data/spec/models/polymorphic/comment_spec.rb +15 -0
  152. data/spec/models/{base → polymorphic}/task_spec.rb +124 -30
  153. data/spec/models/polymorphic/version_spec.rb +1 -1
  154. data/spec/shared/controllers.rb +5 -7
  155. data/spec/shared/models.rb +46 -0
  156. data/spec/spec_helper.rb +3 -4
  157. data/spec/support/mail_processor_mocks.rb +30 -0
  158. data/spec/support/uploaded_file.rb +3 -0
  159. data/spec/views/{common → application}/auto_complete.haml_spec.rb +1 -1
  160. data/vendor/assets/images/jquery-ui/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  161. data/vendor/assets/images/jquery-ui/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  162. data/vendor/assets/images/jquery-ui/ui-bg_flat_10_000000_40x100.png +0 -0
  163. data/vendor/assets/images/jquery-ui/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  164. data/vendor/assets/images/jquery-ui/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  165. data/vendor/assets/images/jquery-ui/ui-bg_glass_65_ffffff_1x400.png +0 -0
  166. data/vendor/assets/images/jquery-ui/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  167. data/vendor/assets/images/jquery-ui/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  168. data/vendor/assets/images/jquery-ui/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  169. data/vendor/assets/images/jquery-ui/ui-icons_222222_256x240.png +0 -0
  170. data/vendor/assets/images/jquery-ui/ui-icons_228ef1_256x240.png +0 -0
  171. data/vendor/assets/images/jquery-ui/ui-icons_ef8c08_256x240.png +0 -0
  172. data/vendor/assets/images/jquery-ui/ui-icons_ffd27a_256x240.png +0 -0
  173. data/vendor/assets/images/jquery-ui/ui-icons_ffffff_256x240.png +0 -0
  174. data/vendor/assets/javascripts/textarea_autocomplete.js +605 -0
  175. data/vendor/assets/stylesheets/jquery-ui.custom.css.erb +565 -0
  176. metadata +234 -154
  177. data/config/locales/simple_form.en.yml +0 -24
  178. data/lib/fat_free_crm/dropbox.rb +0 -439
  179. data/spec/lib/dropbox/email_samples.rb +0 -77
@@ -10,3 +10,5 @@ else
10
10
  page["#{id_prefix}_ask"].show
11
11
  end
12
12
 
13
+
14
+ page.call "crm.textarea_user_autocomplete", "#{id_prefix}_comment_comment"
@@ -25,19 +25,9 @@
25
25
  = a.hidden_field :access, :value => Setting.default_access
26
26
  %tr
27
27
  %td
28
- .label
29
- #{t :account}
30
- %span#account_create_title
31
- (#{t :create_new} #{t :or} <a href='#' onclick='crm.select_account(1); return false;'>#{t :select_existing}</a>):
32
- %span#account_select_title
33
- (<a href='#' onclick='crm.create_account(1); return false;'>#{t :create_new}</a> #{t :or} #{t :select_existing}):
34
- %span#account_disabled_title :
35
-
36
- -# Add [-- None --] account choice when editing existing contact that has an account.
37
- - options = {} and (options[:include_blank] = "" unless @contact.new_record? || @contact.account.blank?)
38
- = account_select(options)
39
-
40
- = a.text_field :name, :style => "width:324px; display:none;"
28
+ != account_select_or_create(a) do |options|
29
+ - # Add [-- None --] account choice when editing existing contact that has an account.
30
+ - options[:include_blank] = "" unless @contact.new_record? || @contact.account.blank?
41
31
  %td= spacer
42
32
  %td
43
33
  .label #{t :assigned_to}:
@@ -11,7 +11,7 @@
11
11
  = image_tag("loading.gif", :size => :thumb, :id => "loading", :style => "display: none;")
12
12
  .remote#options{ hidden }
13
13
  .remote#advanced_search{ hidden_if(!params[:q]) }
14
- - if @search
14
+ - if params[:q]
15
15
  = render :partial => "advanced_search"
16
16
 
17
17
  .remote#create_contact{ hidden }
@@ -1,4 +1,4 @@
1
- unless @contacts.blank?
1
+ if @contacts.any?
2
2
  page[:contacts].replace_html render(:partial => "contact", :collection => @contacts)
3
3
  else
4
4
  page[:contacts].replace_html render(:partial => "shared/empty")
@@ -1,7 +1,7 @@
1
1
  :plain
2
- #{I18n.t(:dropbox_ack_intro)}:
2
+ #{I18n.t(:dropbox_notification_intro)}:
3
3
 
4
- #{I18n.t(:dropbox_ack_to)}:
4
+ #{I18n.t(:dropbox_notification_to)}:
5
5
  #{@mediator_links}
6
6
 
7
7
  #{I18n.t(:subject)}: #{@subject}
@@ -10,6 +10,7 @@ if @attached
10
10
  "assigned"
11
11
  end
12
12
  page.insert_html :top, :tasks, :partial => "tasks/#{view}", :collection => [ @attachment ], :locals => { :bucket => @attachment.computed_bucket }
13
+
13
14
  else
14
15
  page.insert_html :top, params[:assets], :partial => "#{params[:assets]}/#{partial}", :collection => [ @attachment ]
15
16
  if called_from_landing_page?(:accounts)
@@ -18,7 +19,6 @@ if @attached
18
19
  page << refresh_sidebar_for(:campaigns, :show, :summary)
19
20
  end
20
21
  end
21
-
22
22
  end
23
23
 
24
24
  page["#{partial}_#{params[:asset_id]}"].visual_effect :highlight, :duration => 1.5
@@ -1,3 +1,3 @@
1
- contacts = @entity.contacts.paginate(:page => params[:page], :per_page => 20)
1
+ contacts = entity.contacts.paginate(:page => params[:page], :per_page => 20)
2
2
  page['contacts'].replace_html :partial => 'contacts/contact', :collection => contacts
3
3
  page['contacts_pagination'].replace_html will_paginate(contacts, :container => false, :params => {:action => :contacts})
@@ -1,3 +1,3 @@
1
- leads = @entity.leads.paginate(:page => params[:page], :per_page => 20)
1
+ leads = entity.leads.paginate(:page => params[:page], :per_page => 20)
2
2
  page['leads'].replace_html :partial => 'leads/lead', :collection => leads
3
3
  page['leads_pagination'].replace_html will_paginate(leads, :container => false, :params => {:action => :leads})
@@ -1,3 +1,3 @@
1
- opportunities = @entity.opportunities.paginate(:page => params[:page], :per_page => 20)
1
+ opportunities = entity.opportunities.paginate(:page => params[:page], :per_page => 20)
2
2
  page['opportunities'].replace_html :partial => 'opportunities/opportunity', :collection => @opportunities
3
3
  page['opportunities_pagination'].replace_html will_paginate(opportunities, :container => false, :params => {:action => :opportunities})
@@ -0,0 +1,4 @@
1
+ class_name = entity.class.name.downcase
2
+ id = "#{class_name}_#{entity.id}_subscribe"
3
+
4
+ page[id].replace :partial => "comments/subscription_links", :locals => {:entity => entity}
@@ -1,3 +1,3 @@
1
- versions = Version.history(@entity).paginate(:page => params[:page], :per_page => 10)
1
+ versions = Version.history(entity).paginate(:page => params[:page], :per_page => 10)
2
2
  page['versions'].replace_html :partial => 'versions/version', :collection => versions
3
3
  page['versions_pagination'].replace_html will_paginate(versions, :container => false, :params => {:action => :versions})
@@ -1,6 +1,6 @@
1
1
  #footer
2
2
  Powered by #{link_to "Fat Free CRM", "http://www.fatfreecrm.com", :"data-popup" => true }
3
- v#{FatFreeCRM::VERSION} &copy; 2008-#{Date.today.year} by Michael Dvorkin
3
+ v#{FatFreeCRM::VERSION::STRING} &copy; 2008-#{Date.today.year} by Michael Dvorkin
4
4
  \|
5
5
  = image_tag "iconset_attribution.png"
6
6
  Icons from the
@@ -20,6 +20,9 @@
20
20
 
21
21
  :javascript
22
22
  #{yield :javascript}
23
+ var _ffcrm_users = [
24
+ #{User.all.map{|u| "\"#{u.full_name} (@#{u.username})\"" }.join(",\n")}
25
+ ];
23
26
 
24
27
  <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
25
28
  <link rel="icon" href="/favicon.ico" type="image/x-icon">
@@ -14,6 +14,7 @@
14
14
  %td
15
15
  .label.top #{t :company}:
16
16
  = f.text_field :company
17
+ = autocomplete_text_field 'lead_company', Account.order(:name).map(&:name)
17
18
  %tr
18
19
  %td
19
20
  .label #{t :alt_email}:
@@ -11,7 +11,7 @@
11
11
  = image_tag("loading.gif", :size => :thumb, :id => "loading", :style => "display: none;")
12
12
  .remote#options{ hidden }
13
13
  .remote#advanced_search{ hidden_if(!params[:q]) }
14
- - if @search
14
+ - if params[:q]
15
15
  = render :partial => "advanced_search"
16
16
  .remote#create_lead{ hidden }
17
17
 
@@ -1,4 +1,4 @@
1
- unless @leads.blank?
1
+ if @leads.any?
2
2
  page[:leads].replace_html render @leads
3
3
  else
4
4
  page[:leads].replace_html :partial => "shared/empty"
@@ -35,20 +35,10 @@
35
35
  %table
36
36
  %tr
37
37
  %td
38
- .label
39
- #{t :account}
40
- %span#account_create_title
41
- (#{t :create_new} #{t :or} <a href='#' onclick='crm.select_account(1); return false;'>#{t :select_existing}</a>):
42
- %span#account_select_title
43
- (<a href='#' onclick='crm.create_account(1); return false;'>#{t :create_new}</a> #{t :or} #{t :select_existing}):
44
- %span#account_disabled_title :
45
-
46
- -# Add [-- None --] account choice when editing existing opportunity that has an account.
47
- - options = { :selected => @account.id || 0 }
48
- - options[:include_blank] = true #t(:select_none) unless @opportunity.new_record? || @opportunity.account.blank?
49
- = account_select(options)
50
-
51
- = a.text_field :name, :style => "width:324px; display:none;"
38
+ != account_select_or_create(a) do |options|
39
+ -# Add [-- None --] account choice when editing existing opportunity that has an account.
40
+ - options[:selected] = @account.id || 0
41
+ - options[:include_blank] = true #t(:select_none) unless @opportunity.new_record? || @opportunity.account.blank?
52
42
  %td= spacer
53
43
  %td
54
44
  .label.req #{t :assigned_to}:
@@ -11,7 +11,7 @@
11
11
  = image_tag("loading.gif", :size => :thumb, :id => "loading", :style => "display: none;")
12
12
  .remote#options{ hidden }
13
13
  .remote#advanced_search{ hidden_if(!params[:q]) }
14
- - if @search
14
+ - if params[:q]
15
15
  = render :partial => "advanced_search"
16
16
  .remote#create_opportunity{ hidden }
17
17
 
@@ -1,4 +1,4 @@
1
- unless @opportunities.blank?
1
+ if @opportunities.any?
2
2
  page[:opportunities].replace_html render @opportunities
3
3
  else
4
4
  page[:opportunities].replace_html :partial => "shared/empty"
@@ -0,0 +1,7 @@
1
+ <%= I18n.t('comment_notification.intro', :user_full_name => @user.full_name, :entity_type => @entity_type, :entity_name => @entity_name) %>
2
+
3
+ <%= @comment.comment.html_safe %>
4
+
5
+
6
+ --
7
+ <%= I18n.t('comment_notification.reply_instructions', :entity => @entity_type.downcase) %>: <%= polymorphic_url(@entity) %>
@@ -24,7 +24,9 @@ module FatFreeCRM
24
24
  Dir[Rails.root.join("app/controllers/entities")]
25
25
 
26
26
  # Activate observers that should always be running.
27
- config.active_record.observers = :lead_observer, :opportunity_observer, :task_observer unless ARGV.join.include?('assets:precompile')
27
+ unless ARGV.join.include?('assets:precompile')
28
+ config.active_record.observers = :lead_observer, :opportunity_observer, :task_observer
29
+ end
28
30
 
29
31
  # Load development rake tasks (RSpec, Gem packaging, etc.)
30
32
  rake_tasks do
@@ -15,7 +15,7 @@ if defined?(FatFreeCRM::Application)
15
15
  config.action_controller.perform_caching = false
16
16
 
17
17
  # Don't care if the mailer can't send
18
- config.action_mailer.raise_delivery_errors = false
18
+ config.action_mailer.raise_delivery_errors = true
19
19
 
20
20
  # Print deprecation notices to the Rails logger
21
21
  config.active_support.deprecation = :log
@@ -37,6 +37,9 @@ if defined?(FatFreeCRM::Application)
37
37
 
38
38
  # Print deprecation notices to the stderr
39
39
  config.active_support.deprecation = :stderr
40
+
41
+ # Set default host for mailer specs
42
+ config.action_mailer.default_url_options = { :host => "www.example.com" }
40
43
  end
41
44
 
42
45
  # Optionally load 'awesome_print' for debugging in development mode.
@@ -1,9 +1,12 @@
1
- # Configure ActionMailer
1
+ # Configure ActionMailer unless running tests
2
2
 
3
- # Set SMTP settings if present.
4
- if smtp_settings = Setting.smtp
5
- Rails.application.config.action_mailer.delivery_method = :smtp
6
- Rails.application.config.action_mailer.smtp_settings = smtp_settings
3
+ unless Rails.env.test?
4
+ # Set SMTP settings if present.
5
+ smtp_settings = Setting.smtp || {}
6
+ if smtp_settings["address"].present?
7
+ Rails.application.config.action_mailer.delivery_method = :smtp
8
+ Rails.application.config.action_mailer.smtp_settings = smtp_settings
9
+ end
7
10
  end
8
11
 
9
12
  # Set default host for outgoing emails
@@ -0,0 +1,151 @@
1
+ require 'cancan'
2
+
3
+ # Setup
4
+ # =====
5
+ #
6
+ # Put this gist in Rails.root/config/initializers/cancan.rb
7
+ # Add Squeel to Gemfile, see https://github.com/ernie/squeel
8
+ #
9
+ # gem "squeel", "~> 0.9.3"
10
+ #
11
+ # Load Squeel hash and symbol extensions in squeel config initializer
12
+ #
13
+ # Squeel.configure do |config|
14
+ # config.load_core_extensions :hash, :symbol
15
+ # end
16
+ #
17
+ # then you can write
18
+ #
19
+ # can :manage, User, :permissions.outer => {:type.matches => 'Manage%'}}
20
+ #
21
+ # This should offer all the old MetaWhere capabilities,
22
+ # and extra, also allows outer joins
23
+ #
24
+ # you might also be interested in https://gist.github.com/1012332
25
+ # if you use MetaWhere
26
+
27
+ # https://gist.github.com/1523940
28
+ class String
29
+ include Squeel::Nodes::PredicateOperators
30
+ end
31
+
32
+ module Squeel
33
+ module Visitors
34
+ class PredicateVisitor < Visitor
35
+ def visit_String(o, parent)
36
+ Arel::Nodes::SqlLiteral.new(o)
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ module CanCan
43
+
44
+ module ModelAdapters
45
+ class ActiveRecordAdapter < AbstractAdapter
46
+
47
+ def self.override_condition_matching?(subject, name, value)
48
+ name.kind_of?(Squeel::Nodes::Predicate) if defined? Squeel
49
+ end
50
+
51
+ def self.matches_condition?(subject, name, value)
52
+ subject_value = subject.send(name.expr)
53
+ method_name = name.method_name.to_s
54
+ if method_name.ends_with? "_any"
55
+ value.any? { |v| squeel_match? subject_value, method_name.sub("_any", ""), v }
56
+ elsif method_name.ends_with? "_all"
57
+ value.all? { |v| squeel_match? subject_value, method_name.sub("_all", ""), v }
58
+ else
59
+ squeel_match? subject_value, name.method_name, value
60
+ end
61
+ end
62
+
63
+ def self.squeel_match?(subject_value, method, value)
64
+ case method.to_sym
65
+ when :eq then subject_value == value
66
+ when :not_eq then subject_value != value
67
+ when :in then value.include?(subject_value)
68
+ when :not_in then !value.include?(subject_value)
69
+ when :lt then subject_value < value
70
+ when :lteq then subject_value <= value
71
+ when :gt then subject_value > value
72
+ when :gteq then subject_value >= value
73
+ when :matches then subject_value =~ Regexp.new("^" + Regexp.escape(value).gsub("%", ".*") + "$", true)
74
+ when :does_not_match then !squeel_match?(subject_value, :matches, value)
75
+ else raise NotImplemented, "The #{method} Squeel condition is not supported."
76
+ end
77
+ end
78
+
79
+ # mostly let Squeel do the job in building the query
80
+ def conditions
81
+ if @rules.size == 1 && @rules.first.base_behavior
82
+ # Return the conditions directly if there's just one definition
83
+ @rules.first.conditions.dup
84
+ else
85
+ @rules.reverse.inject(false_sql) do |accumulator, rule|
86
+ conditions = rule.conditions.dup
87
+ if conditions.blank?
88
+ rule.base_behavior ? (accumulator | true_sql) : (accumulator & false_sql)
89
+ else
90
+ rule.base_behavior ? (accumulator | conditions) : (accumulator & -conditions)
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ private
97
+
98
+ # override to fix overwrites
99
+ # do not write existing hashes using empty hashes
100
+ def merge_joins(base, add)
101
+ add.each do |name, nested|
102
+ if base[name].is_a?(Hash) && nested.present?
103
+ merge_joins(base[name], nested)
104
+ elsif !base[name].is_a?(Hash) || nested.present?
105
+ base[name] = nested
106
+ end
107
+ end
108
+ end
109
+
110
+ end
111
+ end
112
+
113
+ class Rule
114
+ # allow Squeel
115
+ def matches_conditions_hash?(subject, conditions = @conditions)
116
+ if conditions.empty?
117
+ true
118
+ else
119
+ if model_adapter(subject).override_conditions_hash_matching? subject, conditions
120
+ model_adapter(subject).matches_conditions_hash? subject, conditions
121
+ else
122
+ conditions.all? do |name, value|
123
+ if model_adapter(subject).override_condition_matching? subject, name, value
124
+ model_adapter(subject).matches_condition? subject, name, value
125
+ else
126
+ method_name = case name
127
+ when Symbol then name
128
+ when Squeel::Nodes::Join then name._name
129
+ when Squeel::Nodes::Predicate then name.expr
130
+ else raise name
131
+ end
132
+ attribute = subject.send(method_name)
133
+ if value.kind_of?(Hash)
134
+ if attribute.kind_of? Array
135
+ attribute.any? { |element| matches_conditions_hash? element, value }
136
+ else
137
+ !attribute.nil? && matches_conditions_hash?(attribute, value)
138
+ end
139
+ elsif value.kind_of?(Array) || value.kind_of?(Range)
140
+ value.include? attribute
141
+ else
142
+ attribute == value
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
150
+
151
+ end
@@ -0,0 +1 @@
1
+ ENTITIES = %w(Account Campaign Contact Lead Opportunity).freeze
@@ -0,0 +1,20 @@
1
+ # Fat Free CRM
2
+ # Copyright (C) 2008-2011 by Michael Dvorkin
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Affero General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Affero General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Affero General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+ #------------------------------------------------------------------------------
17
+
18
+ # Set default locale from Settings
19
+
20
+ I18n.default_locale = Setting.locale
@@ -1,11 +1,10 @@
1
1
  require 'paper_trail'
2
2
 
3
- Version.class_eval do
3
+ Version.const_set :ASSETS, %w(all tasks campaigns leads accounts contacts opportunities comments emails)
4
+ Version.const_set :EVENTS, %w(all_events create view update destroy)
5
+ Version.const_set :DURATION, %w(one_hour one_day two_days one_week two_weeks one_month)
4
6
 
5
- ASSETS = %w(all tasks campaigns leads accounts contacts opportunities comments emails)
6
- EVENTS = %w(all_events create view update destroy)
7
- DURATION = %w(one_hour one_day two_days one_week two_weeks one_month)
8
- ENTITIES = %w(Account Campaign Contact Lead Opportunity)
7
+ Version.class_eval do
9
8
 
10
9
  attr_accessible :related
11
10
  belongs_to :related, :polymorphic => true