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.

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
@@ -26,16 +26,7 @@ class HomeController < ApplicationController
26
26
  hook(:home_controller, self, :params => "it works!")
27
27
 
28
28
  @activities = get_activities
29
- respond_to do |format|
30
- format.html # index.html.haml
31
- format.js # index.js.rjs
32
- format.json { render :json => @activities }
33
- format.xml { render :xml => @activities }
34
- format.xls { send_data @activities.to_xls, :type => :xls }
35
- format.csv { send_data @activities.to_csv, :type => :csv }
36
- format.rss { render "index.rss.builder" }
37
- format.atom { render "index.atom.builder" }
38
- end
29
+ respond_with(@activities)
39
30
  end
40
31
 
41
32
  # GET /home/options AJAX
@@ -16,7 +16,6 @@
16
16
  #------------------------------------------------------------------------------
17
17
 
18
18
  class ListsController < ApplicationController
19
- respond_to :js
20
19
 
21
20
  # POST /lists
22
21
  #----------------------------------------------------------------------------
@@ -27,6 +26,7 @@ class ListsController < ApplicationController
27
26
  else
28
27
  @list = List.create(params[:list])
29
28
  end
29
+
30
30
  respond_with(@list)
31
31
  end
32
32
 
@@ -37,8 +37,5 @@ class ListsController < ApplicationController
37
37
  @list.destroy
38
38
 
39
39
  respond_with(@list)
40
-
41
- rescue ActiveRecord::RecordNotFound
42
- respond_to_not_found(:html, :js, :json, :xml)
43
40
  end
44
41
  end
@@ -15,30 +15,26 @@
15
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
  #------------------------------------------------------------------------------
17
17
 
18
- class TasksController < EntitiesController
19
- before_filter :auto_complete, :only => :auto_complete
18
+ class TasksController < ApplicationController
19
+ before_filter :require_user
20
+ before_filter :set_current_tab, :only => [ :index, :show ]
20
21
  before_filter :update_sidebar, :only => :index
21
- skip_after_filter :update_recently_viewed
22
22
 
23
23
  # GET /tasks
24
24
  #----------------------------------------------------------------------------
25
25
  def index
26
26
  @view = params[:view] || "pending"
27
27
  @tasks = Task.find_all_grouped(@current_user, @view)
28
+
28
29
  respond_with(@tasks)
29
30
  end
30
31
 
31
32
  # GET /tasks/1
32
33
  #----------------------------------------------------------------------------
33
34
  def show
34
- respond_to do |format|
35
- format.html { render :index }
36
- format.json { @task = Task.tracked_by(@current_user).find(params[:id]); render :json => @task }
37
- format.xml { @task = Task.tracked_by(@current_user).find(params[:id]); render :xml => @task }
38
- end
35
+ @task = Task.tracked_by(@current_user).find(params[:id])
39
36
 
40
- rescue ActiveRecord::RecordNotFound
41
- respond_to_not_found(:js, :json, :xml)
37
+ respond_with(@task)
42
38
  end
43
39
 
44
40
  # GET /tasks/new
@@ -49,14 +45,17 @@ class TasksController < EntitiesController
49
45
  @users = User.except(@current_user).by_name
50
46
  @bucket = Setting.unroll(:task_bucket)[1..-1] << [ t(:due_specific_date, :default => 'On Specific Date...'), :specific_time ]
51
47
  @category = Setting.unroll(:task_category)
48
+
52
49
  if params[:related]
53
- model, id = params[:related].split("_")
54
- instance_variable_set("@asset", model.classify.constantize.my.find(id))
50
+ model, id = params[:related].split('_')
51
+ if related = model.classify.constantize.my.find_by_id(id)
52
+ instance_variable_set("@asset", related)
53
+ else
54
+ respond_to_related_not_found(model) and return
55
+ end
55
56
  end
56
- respond_with(@task)
57
57
 
58
- rescue ActiveRecord::RecordNotFound # Kicks in if related asset was not found.
59
- respond_to_related_not_found(model, :js) if model
58
+ respond_with(@task)
60
59
  end
61
60
 
62
61
  # GET /tasks/1/edit AJAX
@@ -68,14 +67,12 @@ class TasksController < EntitiesController
68
67
  @bucket = Setting.unroll(:task_bucket)[1..-1] << [ t(:due_specific_date, :default => 'On Specific Date...'), :specific_time ]
69
68
  @category = Setting.unroll(:task_category)
70
69
  @asset = @task.asset if @task.asset_id?
70
+
71
71
  if params[:previous].to_s =~ /(\d+)\z/
72
- @previous = Task.tracked_by(@current_user).find($1)
72
+ @previous = Task.tracked_by(@current_user).find_by_id($1) || $1.to_i
73
73
  end
74
- respond_with(@task)
75
74
 
76
- rescue ActiveRecord::RecordNotFound
77
- @previous ||= $1.to_i
78
- respond_to_not_found(:js) unless @task
75
+ respond_with(@task)
79
76
  end
80
77
 
81
78
  # POST /tasks
@@ -115,9 +112,6 @@ class TasksController < EntitiesController
115
112
  end
116
113
  end
117
114
  end
118
-
119
- rescue ActiveRecord::RecordNotFound
120
- respond_to_not_found(:js, :json, :xml)
121
115
  end
122
116
 
123
117
  # DELETE /tasks/1
@@ -125,7 +119,7 @@ class TasksController < EntitiesController
125
119
  def destroy
126
120
  @view = params[:view] || "pending"
127
121
  @task = Task.tracked_by(@current_user).find(params[:id])
128
- @task.destroy if @task
122
+ @task.destroy
129
123
 
130
124
  # Make sure bucket's div gets hidden if we're deleting last task in the bucket.
131
125
  if Task.bucket_empty?(params[:bucket], @current_user, @view)
@@ -134,9 +128,6 @@ class TasksController < EntitiesController
134
128
 
135
129
  update_sidebar if called_from_index_page?
136
130
  respond_with(@task)
137
-
138
- rescue ActiveRecord::RecordNotFound
139
- respond_to_not_found(:js, :json, :xml)
140
131
  end
141
132
 
142
133
  # PUT /tasks/1/complete
@@ -152,14 +143,11 @@ class TasksController < EntitiesController
152
143
 
153
144
  update_sidebar unless params[:bucket].blank?
154
145
  respond_with(@task)
155
-
156
- rescue ActiveRecord::RecordNotFound
157
- respond_to_not_found(:js, :json, :xml)
158
146
  end
159
147
 
160
148
  # POST /tasks/auto_complete/query AJAX
161
149
  #----------------------------------------------------------------------------
162
- # Handled by before_filter :auto_complete, :only => :auto_complete
150
+ # Handled by ApplicationController :auto_complete
163
151
 
164
152
  # Ajax request to filter out a list of tasks. AJAX
165
153
  #----------------------------------------------------------------------------
@@ -175,7 +163,8 @@ class TasksController < EntitiesController
175
163
  end
176
164
  end
177
165
 
178
- private
166
+ private
167
+
179
168
  # Yields array of current filters and updates the session using new values.
180
169
  #----------------------------------------------------------------------------
181
170
  def update_session
@@ -23,9 +23,9 @@ class UsersController < ApplicationController
23
23
  before_filter :require_and_assign_user, :except => [ :new, :create, :show, :avatar, :upload_avatar ]
24
24
  before_filter :assign_given_or_current_user, :only => [ :show, :avatar, :upload_avatar ]
25
25
 
26
+ load_resource
27
+
26
28
  respond_to :html, :only => [ :show, :new ]
27
- respond_to :js
28
- respond_to :json, :xml, :except => :edit
29
29
 
30
30
  # GET /users/1
31
31
  # GET /users/1.json
@@ -41,7 +41,6 @@ class UsersController < ApplicationController
41
41
  #----------------------------------------------------------------------------
42
42
  def new
43
43
  if can_signup?
44
- @user = User.new
45
44
  respond_with(@user)
46
45
  else
47
46
  redirect_to login_path
@@ -58,7 +57,6 @@ class UsersController < ApplicationController
58
57
  # POST /users.xml HTML
59
58
  #----------------------------------------------------------------------------
60
59
  def create
61
- @user = User.new(params[:user])
62
60
  if @user.save
63
61
  if Setting.user_signup == :needs_approval
64
62
  flash[:notice] = t(:msg_account_created)
@@ -78,6 +76,7 @@ class UsersController < ApplicationController
78
76
  #----------------------------------------------------------------------------
79
77
  def update
80
78
  @user.update_attributes(params[:user])
79
+
81
80
  respond_with(@user)
82
81
  end
83
82
 
@@ -140,6 +139,7 @@ class UsersController < ApplicationController
140
139
  else
141
140
  @user.errors.add(:current_password, t(:msg_invalid_password))
142
141
  end
142
+
143
143
  respond_with(@user)
144
144
  end
145
145
 
@@ -150,7 +150,8 @@ class UsersController < ApplicationController
150
150
  render(:update) { |page| page.redirect_to user_path(@current_user) }
151
151
  end
152
152
 
153
- private
153
+ private
154
+
154
155
  #----------------------------------------------------------------------------
155
156
  def require_and_assign_user
156
157
  require_user
@@ -20,7 +20,7 @@ module AccountsHelper
20
20
  # Sidebar checkbox control for filtering accounts by category.
21
21
  #----------------------------------------------------------------------------
22
22
  def account_category_checbox(category, count)
23
- checked = (session[:filter_by_account_category] ? session[:filter_by_account_category].split(",").include?(category.to_s) : count.to_i > 0)
23
+ checked = (session[:accounts_filter] ? session[:accounts_filter].split(",").include?(category.to_s) : count.to_i > 0)
24
24
  onclick = remote_function(
25
25
  :url => { :action => :filter },
26
26
  :with => h(%Q/"category=" + $$("input[name='category[]']").findAll(function (el) { return el.checked }).pluck("value")/),
@@ -42,13 +42,36 @@ module AccountsHelper
42
42
  end
43
43
 
44
44
  def account_select(options = {})
45
- # Generates a select list with the first 25 accounts,
46
- # and prepends the currently selected account, if available
47
- options[:selected] = (@account && @account.id) || 0
48
- accounts = ([@account] + Account.order("name").my.limit(25)).compact.uniq
49
- collection_select :account, :id, accounts, :id, :name, options,
50
- {:"data-placeholder" => t(:select_an_account),
51
- :style => "width:330px; display:none;" }
45
+ # Generates a select list with the first 25 accounts,
46
+ # and prepends the currently selected account, if available
47
+ options[:selected] = (@account && @account.id) || 0
48
+ accounts = ([@account] + Account.my.order(:name).limit(25)).compact.uniq
49
+ collection_select :account, :id, accounts, :id, :name, options,
50
+ {:"data-placeholder" => t(:select_an_account),
51
+ :style => "width:330px; display:none;" }
52
+ end
53
+
54
+ # Select an existing account or create a new one.
55
+ #----------------------------------------------------------------------------
56
+ def account_select_or_create(form, &block)
57
+ options = {}
58
+ yield options if block_given?
59
+
60
+ content_tag(:div, :class => 'label') do
61
+ t(:account).html_safe +
62
+
63
+ content_tag(:span, :id => 'account_create_title') do
64
+ "(#{t :create_new} #{t :or} <a href='#' onclick='crm.select_account(1); return false;'>#{t :select_existing}</a>):".html_safe
65
+ end.html_safe +
66
+
67
+ content_tag(:span, :id => 'account_select_title') do
68
+ "(<a href='#' onclick='crm.create_account(1); return false;'>#{t :create_new}</a> #{t :or} #{t :select_existing}):".html_safe
69
+ end.html_safe +
70
+
71
+ content_tag(:span, ':', :id => 'account_disabled_title').html_safe
72
+ end.html_safe +
73
+
74
+ account_select(options).html_safe +
75
+ form.text_field(:name, :style => 'width:324px; display:none;')
52
76
  end
53
77
  end
54
-
@@ -332,7 +332,12 @@ module ApplicationHelper
332
332
 
333
333
  #----------------------------------------------------------------------------
334
334
  def default_avatar_url
335
- request.protocol + request.host_with_port + image_path('avatar.jpg')
335
+ url = image_path('avatar.jpg')
336
+ if ActionController::Base.config.asset_host.present?
337
+ url
338
+ else
339
+ request.protocol + request.host_with_port + url
340
+ end
336
341
  end
337
342
 
338
343
  # Returns default permissions intro.
@@ -417,5 +422,14 @@ module ApplicationHelper
417
422
  def link_to_remove_fields(name, f)
418
423
  link_to image_tag('delete.png', :size => '16x16', :alt => name), nil, :class => "remove_fields"
419
424
  end
425
+
426
+ # Adds autocomplete functionality to an existing text field.
427
+ #----------------------------------------------------------------------------
428
+ def autocomplete_text_field(id, values)
429
+ javascript_tag %Q{
430
+ var textField = jQuery('##{id}');
431
+ textField.autocomplete({ source: #{values} });
432
+ }
433
+ end
420
434
  end
421
435
 
@@ -20,7 +20,7 @@ module CampaignsHelper
20
20
  # Sidebar checkbox control for filtering campaigns by status.
21
21
  #----------------------------------------------------------------------------
22
22
  def campaign_status_checbox(status, count)
23
- checked = (session[:filter_by_campaign_status] ? session[:filter_by_campaign_status].split(",").include?(status.to_s) : count.to_i > 0)
23
+ checked = (session[:campaigns_filter] ? session[:campaigns_filter].split(",").include?(status.to_s) : count.to_i > 0)
24
24
  onclick = remote_function(
25
25
  :url => { :action => :filter },
26
26
  :with => h(%Q/"status=" + $$("input[name='status[]']").findAll(function (el) { return el.checked }).pluck("value")/),
@@ -16,5 +16,15 @@
16
16
  #------------------------------------------------------------------------------
17
17
 
18
18
  module CommentsHelper
19
- end
20
19
 
20
+ # Generates a list of links for the subscribed users
21
+ def subscribed_user_links(users)
22
+ links = users.map {|user| link_to(user.full_name, user_path(user)) }
23
+ links.join(", ").html_safe
24
+ end
25
+
26
+ def notification_emails_configured?
27
+ config = Setting.email_comment_replies || {}
28
+ config[:server].present? && config[:user].present? && config[:password].present?
29
+ end
30
+ end
@@ -53,7 +53,7 @@ module LeadsHelper
53
53
  # Sidebar checkbox control for filtering leads by status.
54
54
  #----------------------------------------------------------------------------
55
55
  def lead_status_checbox(status, count)
56
- checked = (session[:filter_by_lead_status] ? session[:filter_by_lead_status].split(",").include?(status.to_s) : count.to_i > 0)
56
+ checked = (session[:leads_filter] ? session[:leads_filter].split(",").include?(status.to_s) : count.to_i > 0)
57
57
  onclick = remote_function(
58
58
  :url => { :action => :filter },
59
59
  :with => h(%Q/"status=" + $$("input[name='status[]']").findAll(function (el) { return el.checked }).pluck("value")/),
@@ -20,7 +20,7 @@ module OpportunitiesHelper
20
20
  # Sidebar checkbox control for filtering opportunities by stage.
21
21
  #----------------------------------------------------------------------------
22
22
  def opportunity_stage_checbox(stage, count)
23
- checked = (session[:filter_by_opportunity_stage] ? session[:filter_by_opportunity_stage].split(",").include?(stage.to_s) : count.to_i > 0)
23
+ checked = (session[:opportunities_filter] ? session[:opportunities_filter].split(",").include?(stage.to_s) : count.to_i > 0)
24
24
  onclick = remote_function(
25
25
  :url => { :action => :filter },
26
26
  :with => h(%Q/"stage=" + $$("input[name='stage[]']").findAll(function (el) { return el.checked }).pluck("value")/),
@@ -15,30 +15,19 @@
15
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
  #------------------------------------------------------------------------------
17
17
 
18
- class Notifier < ActionMailer::Base
18
+ class DropboxMailer < ActionMailer::Base
19
19
 
20
- #----------------------------------------------------------------------------
21
- def password_reset_instructions(user)
22
- @edit_password_url = edit_password_url(user.perishable_token)
23
-
24
- mail(:subject => "Fat Free CRM: " + I18n.t(:password_reset_instruction),
25
- :to => user.email,
26
- :from => "Fat Free CRM <noreply@fatfreecrm.com>",
27
- :date => Time.now)
28
- end
29
-
30
- #----------------------------------------------------------------------------
31
- def dropbox_ack_notification(user, from, email, mediator_links)
20
+ def dropbox_notification(user, from, email, mediator_links)
32
21
  I18n.locale = Setting.locale
33
22
  @mediator_links = mediator_links.join("\n")
34
23
  @subject = email.subject
35
24
  @body = email.body_plain
36
25
 
37
- mail(:subject => I18n.t(:dropbox_ack_subject, :subject => email.subject),
26
+ mail :subject => I18n.t(:dropbox_notification_subject, :subject => email.subject),
38
27
  :to => user.email,
39
28
  :from => from,
40
- :date => Time.now)
29
+ :date => Time.now
41
30
  end
42
-
31
+
43
32
  end
44
33
 
@@ -0,0 +1,37 @@
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
+ class SubscriptionMailer < ActionMailer::Base
19
+
20
+ def comment_notification(user, comment)
21
+ @entity = comment.commentable
22
+ @entity_type = @entity.class.to_s
23
+ @entity_name = @entity.respond_to?(:full_name) ? @entity.full_name : @entity.name
24
+
25
+ @comment = comment
26
+ @user = comment.user
27
+
28
+ # If entity has tags, join them and wrap in parantheses
29
+ subject = "RE: [#{@entity_type.downcase}:#{@entity.id}] #{@entity_name}"
30
+ subject << " (#{@entity.tag_list.join(', ')})" if @entity.tag_list.any?
31
+
32
+ mail :subject => subject,
33
+ :to => user.email,
34
+ :from => "#{@user.full_name} <#{Setting.email_comment_replies[:address]}>",
35
+ :date => Time.now
36
+ end
37
+ end
@@ -15,18 +15,16 @@
15
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
  #------------------------------------------------------------------------------
17
17
 
18
- namespace :ffcrm do
19
- namespace :dropbox do
20
- desc "Run dropbox crawler and process incoming emails"
21
- task :run => :environment do
22
- crawler = FatFreeCRM::Dropbox.new
23
- crawler.run
24
- end
25
-
26
- desc "Set up email dropbox based on currently loaded settings"
27
- task :setup => :environment do
28
- crawler = FatFreeCRM::Dropbox.new
29
- crawler.setup
30
- end
18
+ class UserMailer < ActionMailer::Base
19
+
20
+ def password_reset_instructions(user)
21
+ @edit_password_url = edit_password_url(user.perishable_token)
22
+
23
+ mail :subject => "Fat Free CRM: " + I18n.t(:password_reset_instruction),
24
+ :to => user.email,
25
+ :from => "Fat Free CRM <noreply@fatfreecrm.com>",
26
+ :date => Time.now
31
27
  end
28
+
32
29
  end
30
+