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.
- 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
|