fat_free_crm 0.11.1 → 0.11.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.
Potentially problematic release.
This version of fat_free_crm might be problematic. Click here for more details.
- data/Gemfile +30 -12
- data/Gemfile.lock +131 -119
- data/Procfile +1 -1
- data/README.md +1 -1
- data/app/assets/images/notifications.png +0 -0
- data/app/assets/javascripts/application.js.erb +3 -0
- data/app/assets/javascripts/crm_textarea_autocomplete.js +44 -0
- data/app/assets/stylesheets/application.css.erb +2 -0
- data/app/assets/stylesheets/common.scss +7 -11
- data/app/assets/stylesheets/textarea_autocomplete.scss +42 -0
- data/app/controllers/admin/application_controller.rb +5 -5
- data/app/controllers/admin/field_groups_controller.rb +11 -51
- data/app/controllers/admin/fields_controller.rb +13 -59
- data/app/controllers/admin/plugins_controller.rb +1 -4
- data/app/controllers/admin/settings_controller.rb +0 -4
- data/app/controllers/admin/tags_controller.rb +11 -66
- data/app/controllers/admin/users_controller.rb +20 -83
- data/app/controllers/application_controller.rb +83 -69
- data/app/controllers/comments_controller.rb +12 -29
- data/app/controllers/emails_controller.rb +1 -5
- data/app/controllers/entities/accounts_controller.rb +13 -32
- data/app/controllers/entities/campaigns_controller.rb +17 -32
- data/app/controllers/entities/contacts_controller.rb +20 -38
- data/app/controllers/entities/leads_controller.rb +33 -55
- data/app/controllers/entities/opportunities_controller.rb +26 -42
- data/app/controllers/entities_controller.rb +92 -83
- data/app/controllers/home_controller.rb +1 -10
- data/app/controllers/lists_controller.rb +1 -4
- data/app/controllers/{entities/tasks_controller.rb → tasks_controller.rb} +21 -32
- data/app/controllers/users_controller.rb +6 -5
- data/app/helpers/accounts_helper.rb +32 -9
- data/app/helpers/application_helper.rb +15 -1
- data/app/helpers/campaigns_helper.rb +1 -1
- data/app/helpers/comments_helper.rb +11 -1
- data/app/helpers/leads_helper.rb +1 -1
- data/app/helpers/opportunities_helper.rb +1 -1
- data/app/{models/mailers/notifier.rb → mailers/dropbox_mailer.rb} +5 -16
- data/app/mailers/subscription_mailer.rb +37 -0
- data/{lib/tasks/dropbox.rake → app/mailers/user_mailer.rb} +11 -13
- data/app/models/entities/account.rb +3 -1
- data/app/models/entities/campaign.rb +3 -1
- data/app/models/entities/contact.rb +3 -1
- data/app/models/entities/lead.rb +6 -5
- data/app/models/entities/opportunity.rb +3 -1
- data/app/models/fields/field.rb +1 -1
- data/app/models/polymorphic/comment.rb +34 -0
- data/app/models/{entities → polymorphic}/task.rb +16 -3
- data/app/models/setting.rb +15 -15
- data/app/models/users/ability.rb +12 -5
- data/app/models/users/user.rb +7 -2
- data/app/views/accounts/index.html.haml +1 -1
- data/app/views/accounts/index.js.rjs +1 -1
- data/app/views/admin/plugins/index.html.haml +1 -7
- data/app/views/{shared/auto_complete.html.haml → application/_auto_complete.html.haml} +0 -0
- data/app/views/{shared → application}/index.atom.builder +1 -1
- data/app/views/{shared → application}/index.rss.builder +1 -1
- data/app/views/campaigns/index.html.haml +1 -1
- data/app/views/campaigns/index.js.rjs +1 -1
- data/app/views/comments/_new.html.haml +6 -0
- data/app/views/comments/_subscription_links.html.haml +13 -0
- data/app/views/comments/new.js.rjs +2 -0
- data/app/views/contacts/_top_section.html.haml +3 -13
- data/app/views/contacts/index.html.haml +1 -1
- data/app/views/contacts/index.js.rjs +1 -1
- data/app/views/{notifier/dropbox_ack_notification.html.haml → dropbox_mailer/dropbox_notification.html.haml} +2 -2
- data/app/views/{shared → entities}/attach.js.rjs +1 -1
- data/app/views/entities/contacts.js.rjs +1 -1
- data/app/views/{shared/discard.rjs → entities/discard.js.rjs} +0 -0
- data/app/views/entities/leads.js.rjs +1 -1
- data/app/views/entities/opportunities.js.rjs +1 -1
- data/app/views/entities/subscription_update.js.rjs +4 -0
- data/app/views/entities/versions.js.rjs +1 -1
- data/app/views/layouts/_footer.html.haml +1 -1
- data/app/views/layouts/application.html.haml +3 -0
- data/app/views/leads/_contact.html.haml +1 -0
- data/app/views/leads/index.html.haml +1 -1
- data/app/views/leads/index.js.rjs +1 -1
- data/app/views/opportunities/_top_section.html.haml +4 -14
- data/app/views/opportunities/index.html.haml +1 -1
- data/app/views/opportunities/index.js.rjs +1 -1
- data/app/views/subscription_mailer/comment_notification.text.erb +7 -0
- data/app/views/{notifier → user_mailer}/password_reset_instructions.html.haml +0 -0
- data/config/application.rb +3 -1
- data/config/environments/development.rb +1 -1
- data/config/environments/test.rb +3 -0
- data/config/initializers/action_mailer.rb +8 -5
- data/config/initializers/cancan.rb +151 -0
- data/config/initializers/constants.rb +1 -0
- data/config/initializers/locale.rb +20 -0
- data/config/initializers/paper_trail.rb +4 -5
- data/config/initializers/relative_url_root.rb +0 -1
- data/config/initializers/squeel.rb +5 -0
- data/config/locales/cz_fat_free_crm.yml +3 -3
- data/config/locales/de.yml +2 -2
- data/config/locales/de_fat_free_crm.yml +651 -596
- data/config/locales/en-GB_fat_free_crm.yml +3 -3
- data/config/locales/en-US_fat_free_crm.yml +13 -3
- data/config/locales/es_fat_free_crm.yml +3 -3
- data/config/locales/fr-CA_fat_free_crm.yml +3 -3
- data/config/locales/fr_fat_free_crm.yml +3 -3
- data/config/locales/it_fat_free_crm.yml +3 -3
- data/config/locales/pl_fat_free_crm.yml +3 -3
- data/config/locales/pt-BR_fat_free_crm.yml +3 -3
- data/config/locales/ru_fat_free_crm.yml +3 -3
- data/config/locales/sv-SE_fat_free_crm.yml +3 -3
- data/config/locales/th_fat_free_crm.yml +3 -3
- data/config/routes.rb +10 -0
- data/config/settings.default.yml +29 -10
- data/config/unicorn.rb +4 -0
- data/db/migrate/20111201030535_add_field_groups_klass_name.rb +3 -1
- data/db/migrate/20120314080441_add_subscribed_users_to_entities.rb +23 -0
- data/db/migrate/20120405080727_change_subscribed_users_to_set.rb +24 -0
- data/db/migrate/20120405080742_change_further_subscribed_users_to_set.rb +27 -0
- data/db/migrate/20120413034923_add_index_on_versions_item_type.rb +5 -0
- data/db/schema.rb +109 -126
- data/fat_free_crm.gemspec +12 -18
- data/lib/fat_free_crm.rb +0 -1
- data/lib/fat_free_crm/core_ext/array.rb +1 -0
- data/lib/fat_free_crm/gem_dependencies.rb +1 -0
- data/lib/fat_free_crm/mail_processor/base.rb +226 -0
- data/lib/fat_free_crm/mail_processor/comment_replies.rb +86 -0
- data/lib/fat_free_crm/mail_processor/dropbox.rb +288 -0
- data/lib/fat_free_crm/permissions.rb +6 -19
- data/lib/fat_free_crm/renderers.rb +0 -8
- data/lib/fat_free_crm/tabs.rb +1 -1
- data/lib/fat_free_crm/version.rb +1 -1
- data/lib/plugins/country_select/lib/country_select.rb +2 -2
- data/lib/tasks/mail_processing.rake +60 -0
- data/spec/controllers/admin/users_controller_spec.rb +0 -2
- data/spec/controllers/{accounts_controller_spec.rb → entities/accounts_controller_spec.rb} +7 -9
- data/spec/controllers/{campaigns_controller_spec.rb → entities/campaigns_controller_spec.rb} +7 -7
- data/spec/controllers/{contacts_controller_spec.rb → entities/contacts_controller_spec.rb} +5 -9
- data/spec/controllers/{leads_controller_spec.rb → entities/leads_controller_spec.rb} +7 -9
- data/spec/controllers/{opportunities_controller_spec.rb → entities/opportunities_controller_spec.rb} +8 -15
- data/spec/controllers/tasks_controller_spec.rb +1 -5
- data/spec/controllers/users_controller_spec.rb +5 -9
- data/spec/factories/subscription_factories.rb +6 -0
- data/spec/lib/mail_processor/base_spec.rb +164 -0
- data/spec/lib/mail_processor/comment_replies_spec.rb +63 -0
- data/spec/lib/{dropbox_spec.rb → mail_processor/dropbox_spec.rb} +73 -181
- data/spec/lib/mail_processor/sample_emails/dropbox.rb +167 -0
- data/spec/mailers/subscription_mailer_spec.rb +17 -0
- data/spec/models/{base → entities}/account_contact_spec.rb +0 -0
- data/spec/models/{base → entities}/account_opportunity_spec.rb +0 -0
- data/spec/models/{base → entities}/account_spec.rb +4 -0
- data/spec/models/{base → entities}/campaign_spec.rb +4 -0
- data/spec/models/{base → entities}/contact_opportunity_spec.rb +0 -0
- data/spec/models/{base → entities}/contact_spec.rb +4 -0
- data/spec/models/{base → entities}/lead_spec.rb +4 -0
- data/spec/models/{base → entities}/opportunity_spec.rb +4 -0
- data/spec/models/polymorphic/comment_spec.rb +15 -0
- data/spec/models/{base → polymorphic}/task_spec.rb +124 -30
- data/spec/models/polymorphic/version_spec.rb +1 -1
- data/spec/shared/controllers.rb +5 -7
- data/spec/shared/models.rb +46 -0
- data/spec/spec_helper.rb +3 -4
- data/spec/support/mail_processor_mocks.rb +30 -0
- data/spec/support/uploaded_file.rb +3 -0
- data/spec/views/{common → application}/auto_complete.haml_spec.rb +1 -1
- data/vendor/assets/images/jquery-ui/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-bg_flat_10_000000_40x100.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-icons_222222_256x240.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-icons_228ef1_256x240.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-icons_ef8c08_256x240.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-icons_ffd27a_256x240.png +0 -0
- data/vendor/assets/images/jquery-ui/ui-icons_ffffff_256x240.png +0 -0
- data/vendor/assets/javascripts/textarea_autocomplete.js +605 -0
- data/vendor/assets/stylesheets/jquery-ui.custom.css.erb +565 -0
- metadata +234 -154
- data/config/locales/simple_form.en.yml +0 -24
- data/lib/fat_free_crm/dropbox.rb +0 -439
- data/spec/lib/dropbox/email_samples.rb +0 -77
@@ -25,19 +25,9 @@
|
|
25
25
|
= a.hidden_field :access, :value => Setting.default_access
|
26
26
|
%tr
|
27
27
|
%td
|
28
|
-
|
29
|
-
#
|
30
|
-
|
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
|
14
|
+
- if params[:q]
|
15
15
|
= render :partial => "advanced_search"
|
16
16
|
|
17
17
|
.remote#create_contact{ hidden }
|
@@ -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 =
|
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})
|
File without changes
|
@@ -1,3 +1,3 @@
|
|
1
|
-
leads =
|
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 =
|
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})
|
@@ -1,3 +1,3 @@
|
|
1
|
-
versions = Version.history(
|
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} © 2008-#{Date.today.year} by Michael Dvorkin
|
3
|
+
v#{FatFreeCRM::VERSION::STRING} © 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">
|
@@ -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
|
14
|
+
- if params[:q]
|
15
15
|
= render :partial => "advanced_search"
|
16
16
|
.remote#create_lead{ hidden }
|
17
17
|
|
@@ -35,20 +35,10 @@
|
|
35
35
|
%table
|
36
36
|
%tr
|
37
37
|
%td
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
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
|
14
|
+
- if params[:q]
|
15
15
|
= render :partial => "advanced_search"
|
16
16
|
.remote#create_opportunity{ hidden }
|
17
17
|
|
@@ -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) %>
|
File without changes
|
data/config/application.rb
CHANGED
@@ -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
|
-
|
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 =
|
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
|
data/config/environments/test.rb
CHANGED
@@ -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
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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.
|
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
|
-
|
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
|