fat_free_crm 0.11.0 → 0.11.1

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.

Files changed (212) hide show
  1. data/.gitignore +1 -0
  2. data/.travis.yml +2 -2
  3. data/Gemfile +15 -2
  4. data/Gemfile.lock +34 -14
  5. data/README.md +37 -124
  6. data/app/assets/javascripts/application.js.erb +1 -1
  7. data/app/assets/javascripts/crm.js +22 -1
  8. data/app/assets/javascripts/crm_fields.js +2 -3
  9. data/app/assets/javascripts/jquery-noconflict.js +17 -0
  10. data/app/assets/stylesheets/application.css.erb +1 -0
  11. data/app/assets/stylesheets/common.scss +26 -0
  12. data/app/assets/stylesheets/ffcrm_chosen.scss +1 -1
  13. data/app/controllers/admin/application_controller.rb +1 -1
  14. data/app/controllers/application_controller.rb +0 -8
  15. data/app/controllers/{accounts_controller.rb → entities/accounts_controller.rb} +1 -13
  16. data/app/controllers/{campaigns_controller.rb → entities/campaigns_controller.rb} +1 -13
  17. data/app/controllers/{contacts_controller.rb → entities/contacts_controller.rb} +1 -7
  18. data/app/controllers/{leads_controller.rb → entities/leads_controller.rb} +1 -1
  19. data/app/controllers/{opportunities_controller.rb → entities/opportunities_controller.rb} +1 -7
  20. data/app/controllers/{tasks_controller.rb → entities/tasks_controller.rb} +1 -1
  21. data/app/controllers/{base_controller.rb → entities_controller.rb} +32 -1
  22. data/app/controllers/home_controller.rb +9 -9
  23. data/app/controllers/lists_controller.rb +17 -0
  24. data/app/helpers/admin/tags_helper.rb +1 -1
  25. data/app/helpers/application_helper.rb +14 -14
  26. data/app/helpers/crm_tags_helper.rb +1 -1
  27. data/app/helpers/home_helper.rb +13 -15
  28. data/app/helpers/lists_helper.rb +17 -0
  29. data/app/inputs/date_time_input.rb +17 -0
  30. data/app/inputs/text_input.rb +17 -1
  31. data/app/models/{base → entities}/account.rb +0 -1
  32. data/app/models/{base → entities}/account_contact.rb +0 -0
  33. data/app/models/{base → entities}/account_opportunity.rb +0 -0
  34. data/app/models/{base → entities}/campaign.rb +0 -1
  35. data/app/models/{base → entities}/contact.rb +0 -1
  36. data/app/models/{base → entities}/contact_opportunity.rb +0 -0
  37. data/app/models/{base → entities}/lead.rb +0 -1
  38. data/app/models/{base → entities}/opportunity.rb +0 -1
  39. data/app/models/{base → entities}/task.rb +5 -6
  40. data/app/models/list.rb +17 -0
  41. data/app/models/observers/lead_observer.rb +39 -0
  42. data/app/models/observers/opportunity_observer.rb +54 -0
  43. data/app/models/observers/task_observer.rb +41 -0
  44. data/app/models/polymorphic/address.rb +1 -3
  45. data/app/models/polymorphic/avatar.rb +0 -5
  46. data/app/models/polymorphic/comment.rb +2 -11
  47. data/app/models/polymorphic/email.rb +2 -9
  48. data/app/models/polymorphic/tag.rb +17 -0
  49. data/app/models/polymorphic/tagging.rb +17 -0
  50. data/app/models/users/ability.rb +13 -0
  51. data/app/models/users/user.rb +1 -4
  52. data/app/views/accounts/_account.html.haml +10 -6
  53. data/app/views/accounts/index.html.haml +1 -1
  54. data/app/views/accounts/show.html.haml +6 -24
  55. data/app/views/admin/fields/_field.html.haml +6 -6
  56. data/app/views/admin/tags/_tag.html.haml +2 -2
  57. data/app/views/admin/tags/index.html.haml +1 -1
  58. data/app/views/admin/users/_user.html.haml +3 -3
  59. data/app/views/admin/users/index.html.haml +1 -1
  60. data/app/views/campaigns/_campaign.html.haml +9 -5
  61. data/app/views/campaigns/index.html.haml +1 -1
  62. data/app/views/campaigns/show.html.haml +4 -24
  63. data/app/views/comments/_comment.html.haml +17 -14
  64. data/app/views/comments/_edit.html.haml +1 -1
  65. data/app/views/comments/_new.html.haml +3 -3
  66. data/app/views/contacts/_contact.html.haml +33 -15
  67. data/app/views/contacts/_contacts.html.haml +6 -0
  68. data/app/views/contacts/_sidebar_show.html.haml +1 -1
  69. data/app/views/contacts/index.html.haml +1 -1
  70. data/app/views/contacts/show.html.haml +3 -19
  71. data/app/views/emails/_email.html.haml +24 -21
  72. data/app/views/{base → entities}/_advanced_search.html.haml +0 -0
  73. data/app/views/{base → entities}/_condition_fields.html.haml +0 -0
  74. data/app/views/{base → entities}/_grouping_fields.html.haml +0 -0
  75. data/app/views/{base → entities}/_sort_fields.html.haml +0 -0
  76. data/app/views/{base → entities}/advanced_search.js.rjs +0 -0
  77. data/app/views/entities/contacts.js.rjs +3 -0
  78. data/app/views/entities/leads.js.rjs +3 -0
  79. data/app/views/entities/opportunities.js.rjs +3 -0
  80. data/app/views/entities/versions.js.rjs +3 -0
  81. data/app/views/home/_activity.html.haml +19 -18
  82. data/app/views/home/_events_menu.html.haml +8 -0
  83. data/app/views/home/_options.html.haml +2 -3
  84. data/app/views/home/index.html.haml +1 -1
  85. data/app/views/leads/_lead.html.haml +42 -23
  86. data/app/views/leads/_leads.html.haml +6 -0
  87. data/app/views/leads/_sidebar_show.html.haml +1 -1
  88. data/app/views/leads/index.html.haml +1 -1
  89. data/app/views/leads/show.html.haml +3 -13
  90. data/app/views/opportunities/_opportunities.html.haml +6 -0
  91. data/app/views/opportunities/_opportunity.html.haml +23 -11
  92. data/app/views/opportunities/index.html.haml +1 -1
  93. data/app/views/opportunities/show.html.haml +4 -18
  94. data/app/views/shared/_comment.html.haml +3 -3
  95. data/app/views/shared/_edit_comment.html.haml +1 -1
  96. data/app/views/shared/_recent.html.haml +4 -4
  97. data/app/views/shared/_recently.html.haml +3 -3
  98. data/app/views/shared/_timeline.html.haml +2 -3
  99. data/app/views/tasks/_assigned.html.haml +4 -4
  100. data/app/views/tasks/_completed.html.haml +2 -2
  101. data/app/views/tasks/_pending.html.haml +2 -2
  102. data/app/views/tasks/_related.html.haml +4 -5
  103. data/app/views/tasks/_tasks.html.haml +3 -0
  104. data/app/views/tasks/_title.html.haml +1 -1
  105. data/app/views/tasks/index.html.haml +1 -1
  106. data/app/views/users/_avatar.html.haml +2 -2
  107. data/app/views/versions/_version.html.haml +9 -12
  108. data/app/views/versions/_versions.html.haml +11 -0
  109. data/config/application.rb +3 -2
  110. data/config/environments/development.rb +2 -2
  111. data/config/environments/production.rb +0 -4
  112. data/config/environments/staging.rb +1 -1
  113. data/config/initializers/action_mailer.rb +9 -0
  114. data/config/initializers/paper_trail.rb +80 -0
  115. data/config/initializers/relative_url_root.rb +23 -0
  116. data/config/locales/cz_fat_free_crm.yml +1 -1
  117. data/config/locales/en-US_fat_free_crm.yml +22 -17
  118. data/config/locales/fr_fat_free_crm.yml +349 -134
  119. data/config/routes.rb +144 -140
  120. data/config/settings.default.yml +14 -2
  121. data/db/demo/addresses.yml +2 -2
  122. data/db/demo/emails.yml +2 -2
  123. data/db/migrate/20120216042541_is_paranoid_to_paper_trail.rb +1 -2
  124. data/db/migrate/20120309070209_add_versions_related.rb +6 -0
  125. data/db/migrate/20120316045804_activities_to_versions.rb +35 -0
  126. data/db/schema.rb +79 -53
  127. data/fat_free_crm.gemspec +8 -4
  128. data/lib/development_tasks/gem.rake +18 -1
  129. data/lib/development_tasks/license.rake +2 -4
  130. data/lib/development_tasks/rdoc.rake +17 -0
  131. data/lib/development_tasks/rspec.rake +17 -0
  132. data/lib/fat_free_crm.rb +20 -14
  133. data/lib/fat_free_crm/core_ext/array.rb +0 -27
  134. data/lib/fat_free_crm/dropbox.rb +11 -1
  135. data/lib/fat_free_crm/engine.rb +21 -3
  136. data/lib/fat_free_crm/gem_dependencies.rb +26 -0
  137. data/lib/fat_free_crm/gem_ext.rb +18 -1
  138. data/lib/fat_free_crm/gem_ext/active_record/schema_dumper.rb +18 -1
  139. data/lib/fat_free_crm/gem_ext/authlogic/session/cookies.rb +17 -0
  140. data/lib/fat_free_crm/gem_ext/rails/engine.rb +17 -0
  141. data/lib/fat_free_crm/gem_ext/rails/text_helper.rb +17 -0
  142. data/lib/fat_free_crm/gem_ext/rake/task.rb +17 -0
  143. data/lib/fat_free_crm/gem_ext/simple_form/action_view_extensions/form_helper.rb +18 -1
  144. data/lib/fat_free_crm/plugin_dependencies.rb +23 -5
  145. data/lib/fat_free_crm/renderers.rb +17 -0
  146. data/lib/fat_free_crm/syck_yaml.rb +17 -0
  147. data/lib/fat_free_crm/version.rb +1 -1
  148. data/lib/{country_select → plugins/country_select}/MIT-LICENSE +0 -0
  149. data/lib/{country_select → plugins/country_select}/README +0 -0
  150. data/lib/{country_select → plugins/country_select}/init.rb +0 -0
  151. data/lib/{country_select → plugins/country_select}/install.rb +0 -0
  152. data/lib/{country_select → plugins/country_select}/lib/country_select.rb +0 -0
  153. data/lib/{country_select → plugins/country_select}/uninstall.rb +0 -0
  154. data/lib/{gravatar_image_tag → plugins/gravatar_image_tag}/Gemfile +0 -0
  155. data/lib/{gravatar_image_tag → plugins/gravatar_image_tag}/README.textile +0 -0
  156. data/lib/{gravatar_image_tag → plugins/gravatar_image_tag}/ROADMAP.textile +0 -0
  157. data/lib/{gravatar_image_tag → plugins/gravatar_image_tag}/Rakefile +0 -0
  158. data/lib/{gravatar_image_tag → plugins/gravatar_image_tag}/VERSION +0 -0
  159. data/lib/{gravatar_image_tag → plugins/gravatar_image_tag}/gravatar_image_tag.gemspec +0 -0
  160. data/lib/{gravatar_image_tag → plugins/gravatar_image_tag}/init.rb +0 -0
  161. data/lib/{gravatar_image_tag → plugins/gravatar_image_tag}/lib/gravatar_image_tag.rb +0 -0
  162. data/lib/{gravatar_image_tag → plugins/gravatar_image_tag}/spec/gravatar_image_tag_spec.rb +0 -0
  163. data/lib/{gravatar_image_tag → plugins/gravatar_image_tag}/spec/test_helper.rb +0 -0
  164. data/lib/tasks/demo.rake +32 -29
  165. data/lib/tasks/dropbox.rake +1 -1
  166. data/lib/tasks/fat_free_crm.rake +3 -2
  167. data/lib/tasks/plugins.rake +1 -0
  168. data/spec/controllers/accounts_controller_spec.rb +7 -5
  169. data/spec/controllers/campaigns_controller_spec.rb +11 -9
  170. data/spec/controllers/contacts_controller_spec.rb +7 -5
  171. data/spec/controllers/home_controller_spec.rb +2 -2
  172. data/spec/controllers/leads_controller_spec.rb +7 -5
  173. data/spec/controllers/opportunities_controller_spec.rb +7 -5
  174. data/spec/factories/shared_factories.rb +8 -11
  175. data/spec/lib/dropbox_spec.rb +1 -0
  176. data/spec/models/polymorphic/version_spec.rb +247 -0
  177. data/spec/models/users/user_spec.rb +0 -9
  178. data/spec/spec_helper.rb +4 -0
  179. data/spec/views/home/index.haml_spec.rb +1 -1
  180. data/spec/views/home/index.rjs_spec.rb +4 -4
  181. data/spec/views/tasks/new.rjs_spec.rb +2 -2
  182. data/vendor/assets/javascripts/calendar_date_select/format_french.js +24 -0
  183. metadata +167 -126
  184. data/app/models/observers/activity_observer.rb +0 -84
  185. data/app/models/polymorphic/activity.rb +0 -106
  186. data/app/views/accounts/contacts.js.rjs +0 -3
  187. data/app/views/accounts/opportunities.js.rjs +0 -3
  188. data/app/views/campaigns/leads.js.rjs +0 -3
  189. data/app/views/campaigns/opportunities.js.rjs +0 -3
  190. data/app/views/contacts/opportunities.js.rjs +0 -3
  191. data/app/views/home/_actions_menu.html.haml +0 -8
  192. data/lib/dynamic_form/MIT-LICENSE +0 -20
  193. data/lib/dynamic_form/README +0 -13
  194. data/lib/dynamic_form/Rakefile +0 -10
  195. data/lib/dynamic_form/dynamic_form.gemspec +0 -12
  196. data/lib/dynamic_form/init.rb +0 -2
  197. data/lib/dynamic_form/lib/action_view/helpers/dynamic_form.rb +0 -301
  198. data/lib/dynamic_form/lib/action_view/locale/en-US.yml +0 -8
  199. data/lib/dynamic_form/lib/dynamic_form.rb +0 -6
  200. data/lib/dynamic_form/test/dynamic_form_i18n_test.rb +0 -42
  201. data/lib/dynamic_form/test/dynamic_form_test.rb +0 -370
  202. data/lib/dynamic_form/test/test_helper.rb +0 -10
  203. data/lib/responds_to_parent/MIT-LICENSE +0 -20
  204. data/lib/responds_to_parent/README +0 -47
  205. data/lib/responds_to_parent/Rakefile +0 -22
  206. data/lib/responds_to_parent/init.rb +0 -2
  207. data/lib/responds_to_parent/install.rb +0 -2
  208. data/lib/responds_to_parent/lib/responds_to_parent.rb +0 -70
  209. data/lib/responds_to_parent/test/responds_to_parent_test.rb +0 -11
  210. data/lib/responds_to_parent/test/test_helper.rb +0 -7
  211. data/lib/responds_to_parent/uninstall.rb +0 -2
  212. data/spec/models/polymorphic/activity_spec.rb +0 -303
@@ -1,47 +0,0 @@
1
- RespondsToParent
2
- ================
3
-
4
- Adds responds_to_parent to your controller to respond to the parent document of your page.
5
- Make Ajaxy file uploads by posting the form to a hidden iframe, and respond with
6
- RJS to the parent window.
7
-
8
- http://sean.treadway.info/responds-to-parent/
9
-
10
-
11
- Example
12
- =======
13
-
14
- Controller:
15
-
16
- class Test < ActionController::Base
17
- def main
18
- end
19
-
20
- def form_action
21
- # Do stuff with params[:uploaded_file]
22
-
23
- responds_to_parent do
24
- render :update do |page|
25
- page << "alert($('stuff').innerHTML)"
26
- end
27
- end
28
- end
29
- end
30
-
31
- main.rhtml:
32
-
33
- <html>
34
- <body>
35
- <div id="stuff">Here is some stuff</div>
36
-
37
- <form target="frame" action="form_action">
38
- <input type="file" name="uploaded_file"/>
39
- <input type="submit"/>
40
- </form>
41
-
42
- <iframe id='frame' name="frame"></iframe>
43
- </body>
44
- </html>
45
-
46
-
47
- Copyright (c) 2006 Sean Treadway, released under the MIT license
@@ -1,22 +0,0 @@
1
- require 'rake'
2
- require 'rake/testtask'
3
- require 'rake/rdoctask'
4
-
5
- desc 'Default: run unit tests.'
6
- task :default => :test
7
-
8
- desc 'Test the responds_to_parent plugin.'
9
- Rake::TestTask.new(:test) do |t|
10
- t.libs << 'lib'
11
- t.pattern = 'test/**/*_test.rb'
12
- t.verbose = true
13
- end
14
-
15
- desc 'Generate documentation for the responds_to_parent plugin.'
16
- Rake::RDocTask.new(:rdoc) do |rdoc|
17
- rdoc.rdoc_dir = 'rdoc'
18
- rdoc.title = 'RespondsToParent'
19
- rdoc.options << '--line-numbers' << '--inline-source'
20
- rdoc.rdoc_files.include('README')
21
- rdoc.rdoc_files.include('lib/**/*.rb')
22
- end
@@ -1,2 +0,0 @@
1
- ActionController::Base.send :include, RespondsToParent
2
-
@@ -1,2 +0,0 @@
1
- # Install hook code here
2
-
@@ -1,70 +0,0 @@
1
- # Copyright (c) 2006 Sean Treadway
2
- #
3
- # Permission is hereby granted, free of charge, to any person obtaining
4
- # a copy of this software and associated documentation files (the
5
- # "Software"), to deal in the Software without restriction, including
6
- # without limitation the rights to use, copy, modify, merge, publish,
7
- # distribute, sublicense, and/or sell copies of the Software, and to
8
- # permit persons to whom the Software is furnished to do so, subject to
9
- # the following conditions:
10
- #
11
- # The above copyright notice and this permission notice shall be
12
- # included in all copies or substantial portions of the Software.
13
- #
14
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
-
22
-
23
- # Module containing the methods useful for child IFRAME to parent window communication
24
- module RespondsToParent
25
-
26
- # Executes the response body as JavaScript in the context of the parent window.
27
- # Use this method of you are posting a form to a hidden IFRAME or if you would like
28
- # to use IFRAME base RPC.
29
- def responds_to_parent(&block)
30
- yield
31
-
32
- if performed?
33
- # We're returning HTML instead of JS or XML now
34
- response.headers['Content-Type'] = 'text/html; charset=UTF-8'
35
-
36
- # Either pull out a redirect or the request body
37
- script = if response.headers['Location']
38
- #TODO: erase_redirect_results is missing in rails 3.0 has to be implemented
39
- #erase redirect
40
- "document.location.href = #{location.to_s.inspect}"
41
- else
42
- response.body
43
- end
44
-
45
- # Escape quotes, linebreaks and slashes, maintaining previously escaped slashes
46
- # Suggestions for improvement?
47
- script = (script || '').
48
- gsub('\\', '\\\\\\').
49
- gsub(/\r\n|\r|\n/, '\\n').
50
- gsub(/['"]/, '\\\\\&').
51
- gsub('</script>','</scr"+"ipt>')
52
-
53
- # Clear out the previous render to prevent double render
54
- response.request.env['action_controller.instance'].instance_variable_set(:@_response_body, nil)
55
-
56
- # Eval in parent scope and replace document location of this frame
57
- # so back button doesn't replay action on targeted forms
58
- # loc = document.location to be set after parent is updated for IE
59
- # with(window.parent) - pull in variables from parent window
60
- # setTimeout - scope the execution in the windows parent for safari
61
- # window.eval - legal eval for Opera
62
- render :text => "<html><body><script type='text/javascript' charset='utf-8'>
63
- var loc = document.location;
64
- with(window.parent) { setTimeout(function() { window.eval('#{script}'); if (typeof(loc) !== 'undefined') loc.replace('about:blank'); }, 1) };
65
- </script></body></html>".html_safe
66
- end
67
- end
68
- alias respond_to_parent responds_to_parent
69
- end
70
-
@@ -1,11 +0,0 @@
1
- require 'test/unit'
2
- require File.dirname(__FILE__) + '/test_helper'
3
-
4
- class RespondsToParentTest < Test::Unit::TestCase
5
-
6
- def test_truth
7
- assert true
8
- end
9
-
10
- end
11
-
@@ -1,7 +0,0 @@
1
- ENV['RAILS_ENV'] = 'test'
2
- ENV['RAILS_ROOT'] ||= File.dirname(__FILE__) + '/../../../..'
3
-
4
- # Load the testing framework
5
- require File.expand_path(File.join(ENV['RAILS_ROOT'], 'config/environment.rb'))
6
- require 'test_help'
7
-
@@ -1,2 +0,0 @@
1
- # Uninstall hook code here
2
-
@@ -1,303 +0,0 @@
1
- # == Schema Information
2
- #
3
- # Table name: activities
4
- #
5
- # id :integer not null, primary key
6
- # user_id :integer
7
- # subject_id :integer
8
- # subject_type :string(255)
9
- # action :string(32) default("created")
10
- # info :string(255) default("")
11
- # private :boolean default(FALSE)
12
- # created_at :datetime
13
- # updated_at :datetime
14
- #
15
-
16
- require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
17
-
18
- describe Activity do
19
-
20
- before { login }
21
-
22
- it "should create a new instance given valid attributes" do
23
- Activity.create!(:user => FactoryGirl.create(:user), :subject => FactoryGirl.create(:lead))
24
- end
25
-
26
- describe "with multiple activity records" do
27
- before do
28
- @user = FactoryGirl.create(:user)
29
- @actions = %w(created deleted updated viewed).freeze
30
- @actions.each_with_index do |action, index|
31
- FactoryGirl.create(:activity, :action => action, :user => @user, :subject => FactoryGirl.create(:lead))
32
- FactoryGirl.create(:activity, :action => action, :subject => FactoryGirl.create(:lead)) # different user
33
- end
34
- end
35
-
36
- it "should select all activities except one" do
37
- @activities = Activity.for(@user).without_actions(:viewed)
38
- @activities.map(&:action).sort.should == %w(created deleted updated)
39
- end
40
-
41
- it "should select all activities except many" do
42
- @activities = Activity.for(@user).without_actions(:created, :updated, :deleted)
43
- @activities.map(&:action).should == %w(viewed)
44
- end
45
-
46
- it "should select one requested activity" do
47
- @activities = Activity.for(@user).with_actions(:deleted)
48
- @activities.map(&:action).should == %w(deleted)
49
- end
50
-
51
- it "should select many requested activities" do
52
- @activities = Activity.for(@user).with_actions(:created, :updated)
53
- @activities.map(&:action).sort.should == %w(created updated)
54
- end
55
-
56
- it "should select activities for given user" do
57
- @activities = Activity.for(@user)
58
- @activities.map(&:action).sort.should == @actions
59
- end
60
- end
61
-
62
- %w(account campaign contact lead opportunity task).each do |subject|
63
- describe "Create, update, and delete (#{subject})" do
64
- before :each do
65
- @subject = FactoryGirl.create(subject.to_sym, :user => @current_user)
66
- @conditions = [ 'user_id = ? AND subject_id = ? AND subject_type = ? AND action = ?', @current_user.id, @subject.id, @subject.class.name ]
67
- end
68
-
69
- it "should add an activity when creating new #{subject}" do
70
- @activity = Activity.where(@conditions << 'created').first
71
- @activity.should_not == nil
72
- @activity.info.should == (@subject.respond_to?(:full_name) ? @subject.full_name : @subject.name)
73
- end
74
-
75
- it "should add an activity when updating existing #{subject}" do
76
- if @subject.respond_to?(:full_name)
77
- @subject.update_attributes(:first_name => "Billy", :last_name => "Bones")
78
- else
79
- @subject.update_attributes(:name => "Billy Bones")
80
- end
81
- @activity = Activity.where(@conditions << 'updated').first
82
-
83
- @activity.should_not == nil
84
- @activity.info.ends_with?("Billy Bones").should == true
85
- end
86
-
87
- it "should add an activity when deleting #{subject}" do
88
- @subject.destroy
89
- @activity = Activity.where(@conditions << 'deleted').first
90
-
91
- @activity.should_not == nil
92
- @activity.info.should == (@subject.respond_to?(:full_name) ? @subject.full_name : @subject.name)
93
- end
94
-
95
- it "should add an activity when commenting on a #{subject}" do
96
- @comment = FactoryGirl.create(:comment, :commentable => @subject, :user => @current_user)
97
-
98
- @activity = Activity.where(@conditions << 'commented').first
99
- @activity.should_not == nil
100
- @activity.info.should == (@subject.respond_to?(:full_name) ? @subject.full_name : @subject.name)
101
- end
102
- end
103
- end
104
-
105
- %w(account campaign contact lead opportunity).each do |subject|
106
- describe "Recently viewed items (#{subject})" do
107
- before do
108
- @subject = FactoryGirl.create(subject.to_sym, :user => @current_user)
109
- @conditions = [ "user_id = ? AND subject_id = ? AND subject_type = ? AND action = 'viewed'", @current_user.id, @subject.id, @subject.class.name ]
110
- end
111
-
112
- it "creating a new #{subject} should also make it a recently viewed item" do
113
- @activity = Activity.where(@conditions).first
114
-
115
- @activity.should_not == nil
116
- end
117
-
118
- it "updating #{subject} should also mark it as recently viewed" do
119
- @before = Activity.where(@conditions).first
120
- if @subject.respond_to?(:full_name)
121
- @subject.update_attributes(:first_name => "Billy", :last_name => "Bones")
122
- else
123
- @subject.update_attributes(:name => "Billy Bones")
124
- end
125
- @after = Activity.where(@conditions).first
126
-
127
- @before.should_not == nil
128
- @after.should_not == nil
129
- @after.updated_at.should >= @before.updated_at
130
- end
131
-
132
- it "deleting #{subject} should remove it from recently viewed items" do
133
- @subject.destroy
134
- @activity = Activity.where(@conditions).first
135
-
136
- @activity.should be_nil
137
- end
138
-
139
- it "deleting #{subject} should remove it from recently viewed items for all other users" do
140
- @somebody = FactoryGirl.create(:user)
141
- @subject = FactoryGirl.create(subject.to_sym, :user => @somebody, :access => "Public")
142
- FactoryGirl.create(:activity, :user => @somebody, :subject => @subject, :action => "viewed")
143
-
144
- @activity = Activity.where("user_id = ? AND subject_id = ? AND subject_type = ? AND action = 'viewed'", @somebody.id, @subject.id, @subject.class.name).first
145
- @activity.should_not == nil
146
-
147
- # Now @current_user destroys somebody's object: somebody should no longer have it :viewed.
148
- @subject.destroy
149
- @activity = Activity.where("user_id = ? AND subject_id = ? AND subject_type = ? AND action = 'viewed'", @somebody.id, @subject.id, @subject.class.name).first
150
- @activity.should be_nil
151
- end
152
- end
153
- end
154
-
155
- describe "Recently viewed items (task)" do
156
- before do
157
- @task = FactoryGirl.create(:task)
158
- @conditions = [ "subject_id = ? AND subject_type = 'Task'", @task.id ]
159
- end
160
-
161
- it "creating a new task should not add it to recently viewed items list" do
162
- @activities = Activity.where(@conditions)
163
-
164
- @activities.map(&:action).should == %w(created) # but not viewed
165
- end
166
-
167
- it "updating a new task should not add it to recently viewed items list" do
168
- @task.update_attribute(:updated_at, 1.second.ago)
169
- @activities = Activity.where(@conditions)
170
-
171
- @activities.map(&:action).sort.should == %w(created updated) # but not viewed
172
- end
173
- end
174
-
175
- describe "Action refinements for task updates" do
176
- before do
177
- @task = FactoryGirl.create(:task, :user => @current_user)
178
- @conditions = [ "subject_id=? AND subject_type='Task' AND user_id=?", @task.id, @current_user ]
179
- end
180
-
181
- it "should create 'completed' task action" do
182
- @task.update_attribute(:completed_at, 1.second.ago)
183
- @activities = Activity.where(@conditions)
184
-
185
- @activities.map(&:action).sort.should == %w(completed created)
186
- end
187
-
188
- it "should create 'reassigned' task action" do
189
- @task.update_attribute(:assigned_to, @current_user.id + 1)
190
- @activities = Activity.where(@conditions)
191
-
192
- @activities.map(&:action).sort.should == %w(created reassigned)
193
- end
194
-
195
- it "should create 'rescheduled' task action" do
196
- @task.update_attribute(:bucket, "due_tomorrow") # FactoryGirl creates :due_asap task
197
- @activities = Activity.where(@conditions)
198
-
199
- @activities.map(&:action).sort.should == %w(created rescheduled)
200
- end
201
- end
202
-
203
- describe "Rejecting a lead" do
204
- before do
205
- @lead = FactoryGirl.create(:lead, :user => @current_user, :status => "new")
206
- @conditions = [ "subject_id = ? AND subject_type = 'Lead' AND user_id = ?", @lead.id, @current_user ]
207
- end
208
-
209
- it "should create 'rejected' lead action" do
210
- @lead.update_attribute(:status, "rejected")
211
- @activities = Activity.where(@conditions)
212
-
213
- @activities.map(&:action).sort.should == %w(created rejected viewed)
214
- end
215
-
216
- it "should not mark it as recently viewed" do
217
- Activity.delete_all # delete :created and :viewed
218
- @lead.update_attribute(:status, "rejected")
219
- @activities = Activity.where(@conditions)
220
-
221
- @activities.map(&:action).sort.should == %w(rejected) # no :viewed, only :rejected
222
- end
223
- end
224
-
225
- describe "Permissions" do
226
- it "should not show the created/updated activities if the subject is private" do
227
- @subject = FactoryGirl.create(:account, :user => FactoryGirl.create(:user), :access => "Private")
228
- @subject.update_attribute(:updated_at, 1.second.ago)
229
-
230
- @activities = Activity.where('subject_id = ? AND subject_type = ?', @subject.id, @subject.class.name)
231
- @activities.map(&:action).sort.should == %w(created updated viewed)
232
- @activities = Activity.latest({}).visible_to(@current_user)
233
- @activities.should == []
234
- end
235
-
236
- it "should not show the deleted activity if the subject is private" do
237
- @subject = FactoryGirl.create(:account, :user => FactoryGirl.create(:user), :access => "Private")
238
- @subject.destroy
239
-
240
- @activities = Activity.where('subject_id = ? AND subject_type = ?', @subject.id, @subject.class.name)
241
- @activities.map(&:action).sort.should == %w(created deleted)
242
- @activities = Activity.latest({}).visible_to(@current_user)
243
- @activities.should == []
244
- end
245
-
246
- it "should not show created/updated activities if the subject was not shared with the user" do
247
- @user = FactoryGirl.create(:user)
248
- @subject = FactoryGirl.create(:account,
249
- :user => @user,
250
- :access => "Shared",
251
- :permissions => [ FactoryGirl.build(:permission, :user => @user, :asset => @subject) ]
252
- )
253
- @subject.update_attribute(:updated_at, 1.second.ago)
254
-
255
- @activities = Activity.where('subject_id = ? AND subject_type = ?', @subject.id, @subject.class.name)
256
- @activities.map(&:action).sort.should == %w(created updated viewed)
257
- @activities = Activity.latest({}).visible_to(@current_user)
258
- @activities.should == []
259
- end
260
-
261
- it "should not show the deleted activity if the subject was not shared with the user" do
262
- @user = FactoryGirl.create(:user)
263
- @subject = FactoryGirl.create(:account,
264
- :user => @user,
265
- :access => "Shared",
266
- :permissions => [ FactoryGirl.build(:permission, :user => @user, :asset => @subject) ]
267
- )
268
- @subject.destroy
269
-
270
- @activities = Activity.where('subject_id = ? AND subject_type = ?', @subject.id, @subject.class.name)
271
- @activities.map(&:action).sort.should == %w(created deleted)
272
- @activities = Activity.latest({}).visible_to(@current_user)
273
- @activities.should == []
274
- end
275
-
276
- it "should show created/updated activities if the subject was shared with the user" do
277
- @subject = FactoryGirl.create(:account,
278
- :user => FactoryGirl.create(:user),
279
- :access => "Shared",
280
- :permissions => [ FactoryGirl.build(:permission, :user => @current_user, :asset => @subject) ]
281
- )
282
- @subject.update_attribute(:updated_at, 1.second.ago)
283
-
284
- @activities = Activity.where('subject_id = ? AND subject_type = ?', @subject.id, @subject.class.name)
285
- @activities.map(&:action).sort.should == %w(created updated viewed)
286
-
287
- @activities = Activity.latest({}).visible_to(@current_user)
288
- @activities.map(&:action).sort.should == %w(created updated viewed)
289
- end
290
- end
291
-
292
- describe "Exportable" do
293
- before do
294
- Activity.delete_all
295
- FactoryGirl.create(:activity, :user => FactoryGirl.create(:user), :subject => FactoryGirl.create(:account))
296
- FactoryGirl.create(:activity, :user => FactoryGirl.create(:user, :first_name => nil, :last_name => nil), :subject => FactoryGirl.create(:account))
297
- Activity.delete_all("action IS NOT NULL") # Delete created and views actions that are created implicitly.
298
- end
299
- it_should_behave_like("exportable") do
300
- let(:exported) { Activity.all }
301
- end
302
- end
303
- end