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
@@ -28,57 +28,51 @@ class LeadsController < EntitiesController
|
|
28
28
|
# GET /leads/1
|
29
29
|
#----------------------------------------------------------------------------
|
30
30
|
def show
|
31
|
-
@lead = Lead.my.find(params[:id])
|
32
|
-
|
33
31
|
respond_with(@lead) do |format|
|
34
32
|
format.html do
|
35
33
|
@comment = Comment.new
|
36
34
|
@timeline = timeline(@lead)
|
37
35
|
end
|
38
36
|
end
|
39
|
-
|
40
|
-
rescue ActiveRecord::RecordNotFound
|
41
|
-
respond_to_not_found(:html, :json, :xml)
|
42
37
|
end
|
43
38
|
|
44
39
|
# GET /leads/new
|
45
40
|
#----------------------------------------------------------------------------
|
46
41
|
def new
|
47
|
-
@lead =
|
42
|
+
@lead.attributes = {:user => @current_user, :access => Setting.default_access}
|
48
43
|
@users = User.except(@current_user)
|
49
|
-
|
44
|
+
get_campaigns
|
45
|
+
|
50
46
|
if params[:related]
|
51
|
-
model, id = params[:related].split(
|
52
|
-
|
47
|
+
model, id = params[:related].split('_')
|
48
|
+
if related = model.classify.constantize.my.find_by_id(id)
|
49
|
+
instance_variable_set("@#{model}", related)
|
50
|
+
else
|
51
|
+
respond_to_related_not_found(model) and return
|
52
|
+
end
|
53
53
|
end
|
54
|
-
respond_with(@lead)
|
55
54
|
|
56
|
-
|
57
|
-
respond_to_related_not_found(model, :js) if model
|
55
|
+
respond_with(@lead)
|
58
56
|
end
|
59
57
|
|
60
58
|
# GET /leads/1/edit AJAX
|
61
59
|
#----------------------------------------------------------------------------
|
62
60
|
def edit
|
63
|
-
@lead = Lead.my.find(params[:id])
|
64
61
|
@users = User.except(@current_user)
|
65
|
-
|
62
|
+
get_campaigns
|
63
|
+
|
66
64
|
if params[:previous].to_s =~ /(\d+)\z/
|
67
|
-
@previous = Lead.my.
|
65
|
+
@previous = Lead.my.find_by_id($1) || $1.to_i
|
68
66
|
end
|
69
|
-
respond_with(@lead)
|
70
67
|
|
71
|
-
|
72
|
-
@previous ||= $1.to_i
|
73
|
-
respond_to_not_found(:js) unless @lead
|
68
|
+
respond_with(@lead)
|
74
69
|
end
|
75
70
|
|
76
71
|
# POST /leads
|
77
72
|
#----------------------------------------------------------------------------
|
78
73
|
def create
|
79
|
-
@lead = Lead.new(params[:lead])
|
80
74
|
@users = User.except(@current_user)
|
81
|
-
|
75
|
+
get_campaigns
|
82
76
|
|
83
77
|
respond_with(@lead) do |format|
|
84
78
|
if @lead.save_with_permissions(params)
|
@@ -95,61 +89,48 @@ class LeadsController < EntitiesController
|
|
95
89
|
# PUT /leads/1
|
96
90
|
#----------------------------------------------------------------------------
|
97
91
|
def update
|
98
|
-
@lead = Lead.my.find(params[:id])
|
99
|
-
|
100
92
|
respond_with(@lead) do |format|
|
101
93
|
if @lead.update_with_permissions(params[:lead], params[:users])
|
102
94
|
update_sidebar
|
103
95
|
else
|
104
96
|
@users = User.except(@current_user)
|
105
|
-
@campaigns = Campaign.my.order(
|
97
|
+
@campaigns = Campaign.my.order('name')
|
106
98
|
end
|
107
99
|
end
|
108
|
-
|
109
|
-
rescue ActiveRecord::RecordNotFound
|
110
|
-
respond_to_not_found(:js, :json, :xml)
|
111
100
|
end
|
112
101
|
|
113
102
|
# DELETE /leads/1
|
114
103
|
#----------------------------------------------------------------------------
|
115
104
|
def destroy
|
116
|
-
@lead
|
117
|
-
@lead.destroy if @lead
|
105
|
+
@lead.destroy
|
118
106
|
|
119
107
|
respond_with(@lead) do |format|
|
120
108
|
format.html { respond_to_destroy(:html) }
|
121
109
|
format.js { respond_to_destroy(:ajax) }
|
122
110
|
end
|
123
|
-
|
124
|
-
rescue ActiveRecord::RecordNotFound
|
125
|
-
respond_to_not_found(:html, :js, :json, :xml)
|
126
111
|
end
|
127
112
|
|
128
113
|
# GET /leads/1/convert
|
129
114
|
#----------------------------------------------------------------------------
|
130
115
|
def convert
|
131
|
-
@lead = Lead.my.find(params[:id])
|
132
116
|
@users = User.except(@current_user)
|
133
117
|
@account = Account.new(:user => @current_user, :name => @lead.company, :access => "Lead")
|
134
|
-
@accounts = Account.my.order(
|
118
|
+
@accounts = Account.my.order('name')
|
135
119
|
@opportunity = Opportunity.new(:user => @current_user, :access => "Lead", :stage => "prospecting", :campaign => @lead.campaign, :source => @lead.source)
|
120
|
+
|
136
121
|
if params[:previous].to_s =~ /(\d+)\z/
|
137
|
-
@previous = Lead.my.
|
122
|
+
@previous = Lead.my.find_by_id($1) || $1.to_i
|
138
123
|
end
|
139
|
-
respond_with(@lead)
|
140
124
|
|
141
|
-
|
142
|
-
@previous ||= $1.to_i
|
143
|
-
respond_to_not_found(:js, :json, :xml) unless @lead
|
125
|
+
respond_with(@lead)
|
144
126
|
end
|
145
127
|
|
146
128
|
# PUT /leads/1/promote
|
147
129
|
#----------------------------------------------------------------------------
|
148
130
|
def promote
|
149
|
-
@lead = Lead.my.find(params[:id])
|
150
131
|
@users = User.except(@current_user)
|
151
132
|
@account, @opportunity, @contact = @lead.promote(params)
|
152
|
-
@accounts = Account.my.order(
|
133
|
+
@accounts = Account.my.order('name')
|
153
134
|
@stage = Setting.unroll(:opportunity_stage)
|
154
135
|
|
155
136
|
respond_with(@lead) do |format|
|
@@ -161,33 +142,26 @@ class LeadsController < EntitiesController
|
|
161
142
|
format.xml { render :xml => @account.errors + @opportunity.errors + @contact.errors, :status => :unprocessable_entity }
|
162
143
|
end
|
163
144
|
end
|
164
|
-
|
165
|
-
rescue ActiveRecord::RecordNotFound
|
166
|
-
respond_to_not_found(:js, :json, :xml)
|
167
145
|
end
|
168
146
|
|
169
147
|
# PUT /leads/1/reject
|
170
148
|
#----------------------------------------------------------------------------
|
171
149
|
def reject
|
172
|
-
@lead
|
173
|
-
@lead.reject if @lead
|
150
|
+
@lead.reject
|
174
151
|
update_sidebar
|
175
152
|
|
176
153
|
respond_with(@lead) do |format|
|
177
154
|
format.html { flash[:notice] = t(:msg_asset_rejected, @lead.full_name); redirect_to leads_path }
|
178
155
|
end
|
179
|
-
|
180
|
-
rescue ActiveRecord::RecordNotFound
|
181
|
-
respond_to_not_found(:html, :js, :json, :xml)
|
182
156
|
end
|
183
157
|
|
184
158
|
# PUT /leads/1/attach
|
185
159
|
#----------------------------------------------------------------------------
|
186
|
-
# Handled by
|
160
|
+
# Handled by EntitiesController :attach
|
187
161
|
|
188
162
|
# POST /leads/1/discard
|
189
163
|
#----------------------------------------------------------------------------
|
190
|
-
# Handled by
|
164
|
+
# Handled by EntitiesController :discard
|
191
165
|
|
192
166
|
# POST /leads/auto_complete/query AJAX
|
193
167
|
#----------------------------------------------------------------------------
|
@@ -229,15 +203,19 @@ class LeadsController < EntitiesController
|
|
229
203
|
# POST /leads/filter AJAX
|
230
204
|
#----------------------------------------------------------------------------
|
231
205
|
def filter
|
232
|
-
session[:
|
206
|
+
session[:leads_filter] = params[:status]
|
233
207
|
@leads = get_leads(:page => 1) # Start one the first page.
|
234
208
|
render :index
|
235
209
|
end
|
236
210
|
|
237
|
-
|
211
|
+
private
|
212
|
+
|
213
|
+
#----------------------------------------------------------------------------
|
214
|
+
alias :get_leads :get_list_of_records
|
215
|
+
|
238
216
|
#----------------------------------------------------------------------------
|
239
|
-
def
|
240
|
-
|
217
|
+
def get_campaigns
|
218
|
+
@campaigns = Campaign.my.order('name')
|
241
219
|
end
|
242
220
|
|
243
221
|
#----------------------------------------------------------------------------
|
@@ -18,7 +18,7 @@
|
|
18
18
|
class OpportunitiesController < EntitiesController
|
19
19
|
before_filter :load_settings
|
20
20
|
before_filter :get_data_for_sidebar, :only => :index
|
21
|
-
before_filter :set_params, :only => [:index, :redraw, :filter]
|
21
|
+
before_filter :set_params, :only => [ :index, :redraw, :filter ]
|
22
22
|
|
23
23
|
# GET /opportunities
|
24
24
|
#----------------------------------------------------------------------------
|
@@ -30,58 +30,51 @@ class OpportunitiesController < EntitiesController
|
|
30
30
|
# GET /opportunities/1
|
31
31
|
#----------------------------------------------------------------------------
|
32
32
|
def show
|
33
|
-
@opportunity = Opportunity.my.find(params[:id])
|
34
|
-
|
35
33
|
respond_with(@opportunity) do |format|
|
36
34
|
format.html do
|
37
35
|
@comment = Comment.new
|
38
36
|
@timeline = timeline(@opportunity)
|
39
37
|
end
|
40
38
|
end
|
41
|
-
|
42
|
-
rescue ActiveRecord::RecordNotFound
|
43
|
-
respond_to_not_found(:html, :json, :xml)
|
44
39
|
end
|
45
40
|
|
46
41
|
# GET /opportunities/new
|
47
42
|
#----------------------------------------------------------------------------
|
48
43
|
def new
|
49
|
-
@opportunity =
|
44
|
+
@opportunity.attributes = {:user => @current_user, :stage => "prospecting", :access => Setting.default_access}
|
50
45
|
@users = User.except(@current_user)
|
51
|
-
@account = Account.new(:user => @current_user)
|
52
|
-
@accounts = Account.my.order(
|
46
|
+
@account = Account.new(:user => @current_user, :access => Setting.default_access)
|
47
|
+
@accounts = Account.my.order('name')
|
48
|
+
|
53
49
|
if params[:related]
|
54
|
-
model, id = params[:related].split(
|
55
|
-
|
50
|
+
model, id = params[:related].split('_')
|
51
|
+
if related = model.classify.constantize.my.find_by_id(id)
|
52
|
+
instance_variable_set("@#{model}", related)
|
53
|
+
else
|
54
|
+
respond_to_related_not_found(model) and return
|
55
|
+
end
|
56
56
|
end
|
57
|
-
respond_with(@opportunity)
|
58
57
|
|
59
|
-
|
60
|
-
respond_to_related_not_found(model, :js) if model
|
58
|
+
respond_with(@opportunity)
|
61
59
|
end
|
62
60
|
|
63
61
|
# GET /opportunities/1/edit AJAX
|
64
62
|
#----------------------------------------------------------------------------
|
65
63
|
def edit
|
66
|
-
@opportunity = Opportunity.my.find(params[:id])
|
67
64
|
@users = User.except(@current_user)
|
68
65
|
@account = @opportunity.account || Account.new(:user => @current_user)
|
69
|
-
@accounts = Account.my.order(
|
66
|
+
@accounts = Account.my.order('name')
|
67
|
+
|
70
68
|
if params[:previous].to_s =~ /(\d+)\z/
|
71
|
-
@previous = Opportunity.my.
|
69
|
+
@previous = Opportunity.my.find_by_id($1) || $1.to_i
|
72
70
|
end
|
73
|
-
respond_with(@opportunity)
|
74
71
|
|
75
|
-
|
76
|
-
@previous ||= $1.to_i
|
77
|
-
respond_to_not_found(:js) unless @opportunity
|
72
|
+
respond_with(@opportunity)
|
78
73
|
end
|
79
74
|
|
80
75
|
# POST /opportunities
|
81
76
|
#----------------------------------------------------------------------------
|
82
77
|
def create
|
83
|
-
@opportunity = Opportunity.new(params[:opportunity])
|
84
|
-
|
85
78
|
respond_with(@opportunity) do |format|
|
86
79
|
if @opportunity.save_with_account_and_permissions(params)
|
87
80
|
if called_from_index_page?
|
@@ -94,7 +87,7 @@ class OpportunitiesController < EntitiesController
|
|
94
87
|
end
|
95
88
|
else
|
96
89
|
@users = User.except(@current_user)
|
97
|
-
@accounts = Account.my.order(
|
90
|
+
@accounts = Account.my.order('name')
|
98
91
|
unless params[:account][:id].blank?
|
99
92
|
@account = Account.find(params[:account][:id])
|
100
93
|
else
|
@@ -113,8 +106,6 @@ class OpportunitiesController < EntitiesController
|
|
113
106
|
# PUT /opportunities/1
|
114
107
|
#----------------------------------------------------------------------------
|
115
108
|
def update
|
116
|
-
@opportunity = Opportunity.my.find(params[:id])
|
117
|
-
|
118
109
|
respond_with(@opportunity) do |format|
|
119
110
|
if @opportunity.update_with_account_and_permissions(params)
|
120
111
|
if called_from_index_page?
|
@@ -126,7 +117,7 @@ class OpportunitiesController < EntitiesController
|
|
126
117
|
end
|
127
118
|
else
|
128
119
|
@users = User.except(@current_user)
|
129
|
-
@accounts = Account.my.order(
|
120
|
+
@accounts = Account.my.order('name')
|
130
121
|
if @opportunity.account
|
131
122
|
@account = Account.find(@opportunity.account.id)
|
132
123
|
else
|
@@ -134,38 +125,31 @@ class OpportunitiesController < EntitiesController
|
|
134
125
|
end
|
135
126
|
end
|
136
127
|
end
|
137
|
-
|
138
|
-
rescue ActiveRecord::RecordNotFound
|
139
|
-
respond_to_not_found(:js, :json, :xml)
|
140
128
|
end
|
141
129
|
|
142
130
|
# DELETE /opportunities/1
|
143
131
|
#----------------------------------------------------------------------------
|
144
132
|
def destroy
|
145
|
-
@opportunity = Opportunity.my.find(params[:id])
|
146
133
|
if called_from_landing_page?(:accounts)
|
147
134
|
@account = @opportunity.account # Reload related account if any.
|
148
135
|
elsif called_from_landing_page?(:campaigns)
|
149
136
|
@campaign = @opportunity.campaign # Reload related campaign if any.
|
150
137
|
end
|
151
|
-
@opportunity.destroy
|
138
|
+
@opportunity.destroy
|
152
139
|
|
153
140
|
respond_with(@opportunity) do |format|
|
154
141
|
format.html { respond_to_destroy(:html) }
|
155
142
|
format.js { respond_to_destroy(:ajax) }
|
156
143
|
end
|
157
|
-
|
158
|
-
rescue ActiveRecord::RecordNotFound
|
159
|
-
respond_to_not_found(:html, :js, :json, :xml)
|
160
144
|
end
|
161
145
|
|
162
146
|
# PUT /opportunities/1/attach
|
163
147
|
#----------------------------------------------------------------------------
|
164
|
-
# Handled by
|
148
|
+
# Handled by EntitiesController :attach
|
165
149
|
|
166
150
|
# POST /opportunities/1/discard
|
167
151
|
#----------------------------------------------------------------------------
|
168
|
-
# Handled by
|
152
|
+
# Handled by EntitiesController :discard
|
169
153
|
|
170
154
|
# POST /opportunities/auto_complete/query AJAX
|
171
155
|
#----------------------------------------------------------------------------
|
@@ -195,11 +179,10 @@ class OpportunitiesController < EntitiesController
|
|
195
179
|
render :index
|
196
180
|
end
|
197
181
|
|
198
|
-
|
182
|
+
private
|
183
|
+
|
199
184
|
#----------------------------------------------------------------------------
|
200
|
-
|
201
|
-
get_list_of_records(Opportunity, options.merge!(:filter => :filter_by_opportunity_stage))
|
202
|
-
end
|
185
|
+
alias :get_opportunities :get_list_of_records
|
203
186
|
|
204
187
|
#----------------------------------------------------------------------------
|
205
188
|
def respond_to_destroy(method)
|
@@ -241,10 +224,11 @@ class OpportunitiesController < EntitiesController
|
|
241
224
|
@stage = Setting.unroll(:opportunity_stage)
|
242
225
|
end
|
243
226
|
|
227
|
+
#----------------------------------------------------------------------------
|
244
228
|
def set_params
|
245
229
|
@current_user.pref[:opportunities_per_page] = params[:per_page] if params[:per_page]
|
246
230
|
@current_user.pref[:opportunities_outline] = params[:outline] if params[:outline]
|
247
231
|
@current_user.pref[:opportunities_sort_by] = Opportunity::sort_by_map[params[:sort_by]] if params[:sort_by]
|
248
|
-
session[:
|
232
|
+
session[:opportunities_filter] = params[:stage] if params[:stage]
|
249
233
|
end
|
250
234
|
end
|
@@ -18,119 +18,105 @@
|
|
18
18
|
class EntitiesController < ApplicationController
|
19
19
|
before_filter :require_user
|
20
20
|
before_filter :set_current_tab, :only => [ :index, :show ]
|
21
|
-
after_filter :update_recently_viewed, :only => :show
|
22
21
|
|
23
|
-
|
24
|
-
respond_to :js
|
25
|
-
respond_to :json, :xml, :except => :edit
|
26
|
-
respond_to :atom, :csv, :rss, :xls, :only => :index
|
22
|
+
load_and_authorize_resource
|
27
23
|
|
28
|
-
|
24
|
+
after_filter :update_recently_viewed, :only => :show
|
29
25
|
|
30
|
-
|
31
|
-
#----------------------------------------------------------------------------
|
32
|
-
def auto_complete
|
33
|
-
@query = params[:auto_complete_query]
|
34
|
-
@auto_complete = hook(:auto_complete, self, :query => @query, :user => @current_user)
|
35
|
-
if @auto_complete.empty?
|
36
|
-
@auto_complete = klass.my.text_search(@query).limit(10)
|
37
|
-
else
|
38
|
-
@auto_complete = @auto_complete.last
|
39
|
-
end
|
40
|
-
session[:auto_complete] = controller_name.to_sym
|
41
|
-
respond_to do |format|
|
42
|
-
format.any(:js, :html) { render "shared/auto_complete", :layout => nil }
|
43
|
-
format.json { render :json => @auto_complete.inject({}){|h,a| h[a.id] = a.name; h } }
|
44
|
-
end
|
45
|
-
end
|
26
|
+
helper_method :entity, :entities, :search
|
46
27
|
|
47
28
|
# Common attach handler for all core controllers.
|
48
29
|
#----------------------------------------------------------------------------
|
49
30
|
def attach
|
50
|
-
model = klass.my.find(params[:id])
|
51
31
|
@attachment = params[:assets].classify.constantize.find(params[:asset_id])
|
52
|
-
@attached =
|
53
|
-
|
54
|
-
@campaign = model.reload if model.is_a?(Campaign)
|
55
|
-
|
56
|
-
respond_to do |format|
|
57
|
-
format.js { render "shared/attach" }
|
58
|
-
format.json { render :json => model.reload }
|
59
|
-
format.xml { render :xml => model.reload }
|
60
|
-
end
|
32
|
+
@attached = entity.attach!(@attachment)
|
33
|
+
entity.reload
|
61
34
|
|
62
|
-
|
63
|
-
respond_to_not_found(:html, :js, :json, :xml)
|
35
|
+
respond_with(entity)
|
64
36
|
end
|
65
37
|
|
66
38
|
# Common discard handler for all core controllers.
|
67
39
|
#----------------------------------------------------------------------------
|
68
40
|
def discard
|
69
|
-
model = klass.my.find(params[:id])
|
70
41
|
@attachment = params[:attachment].constantize.find(params[:attachment_id])
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
42
|
+
entity.discard!(@attachment)
|
43
|
+
entity.reload
|
44
|
+
|
45
|
+
respond_with(entity)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Common subscribe handler for all core controllers.
|
49
|
+
#----------------------------------------------------------------------------
|
50
|
+
def subscribe
|
51
|
+
entity.subscribed_users += [current_user.id]
|
52
|
+
entity.save
|
53
|
+
|
54
|
+
respond_with(entity) do |format|
|
55
|
+
format.js { render 'subscription_update' }
|
79
56
|
end
|
57
|
+
end
|
80
58
|
|
81
|
-
|
82
|
-
|
59
|
+
# Common unsubscribe handler for all core controllers.
|
60
|
+
#----------------------------------------------------------------------------
|
61
|
+
def unsubscribe
|
62
|
+
entity.subscribed_users -= [current_user.id]
|
63
|
+
entity.save
|
64
|
+
|
65
|
+
respond_with(entity) do |format|
|
66
|
+
format.js { render 'subscription_update' }
|
67
|
+
end
|
83
68
|
end
|
84
69
|
|
85
70
|
# GET /entities/contacts AJAX
|
86
71
|
#----------------------------------------------------------------------------
|
87
72
|
def contacts
|
88
|
-
@entity = klass.my.find(params[:id])
|
89
73
|
end
|
90
74
|
|
91
75
|
# GET /entities/leads AJAX
|
92
76
|
#----------------------------------------------------------------------------
|
93
77
|
def leads
|
94
|
-
@entity = klass.my.find(params[:id])
|
95
78
|
end
|
96
79
|
|
97
80
|
# GET /entities/opportunities AJAX
|
98
81
|
#----------------------------------------------------------------------------
|
99
82
|
def opportunities
|
100
|
-
@entity = klass.my.find(params[:id])
|
101
83
|
end
|
102
84
|
|
103
85
|
# GET /entities/versions AJAX
|
104
86
|
#----------------------------------------------------------------------------
|
105
87
|
def versions
|
106
|
-
@entity = klass.my.find(params[:id])
|
107
88
|
end
|
108
89
|
|
109
|
-
|
110
|
-
|
90
|
+
protected
|
91
|
+
|
92
|
+
#----------------------------------------------------------------------------
|
93
|
+
def entity=(entity)
|
94
|
+
instance_variable_set("@#{controller_name.singularize}", entity)
|
111
95
|
end
|
112
96
|
|
113
|
-
# Controller instance method that responds to /controlled/tagged/tag request.
|
114
|
-
# It stores given tag as current query and redirect to index to display all
|
115
|
-
# records tagged with the tag.
|
116
97
|
#----------------------------------------------------------------------------
|
117
|
-
def
|
118
|
-
|
119
|
-
redirect_to :action => "index"
|
98
|
+
def entity
|
99
|
+
instance_variable_get("@#{controller_name.singularize}")
|
120
100
|
end
|
121
101
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
@asset = klass.find_by_id(params[:asset_id]) || klass.new
|
126
|
-
render 'fields/group' and return
|
127
|
-
end
|
128
|
-
end
|
129
|
-
render :text => ''
|
102
|
+
#----------------------------------------------------------------------------
|
103
|
+
def entities=(entities)
|
104
|
+
instance_variable_set("@#{controller_name}", entities)
|
130
105
|
end
|
131
106
|
|
132
|
-
|
107
|
+
#----------------------------------------------------------------------------
|
108
|
+
def entities
|
109
|
+
instance_variable_get("@#{controller_name}") || klass.my
|
110
|
+
end
|
133
111
|
|
112
|
+
private
|
113
|
+
|
114
|
+
#----------------------------------------------------------------------------
|
115
|
+
def get_users
|
116
|
+
@users ||= User.except(current_user)
|
117
|
+
end
|
118
|
+
|
119
|
+
#----------------------------------------------------------------------------
|
134
120
|
def search
|
135
121
|
@search ||= begin
|
136
122
|
search = klass.search(params[:q])
|
@@ -141,46 +127,69 @@ class EntitiesController < ApplicationController
|
|
141
127
|
|
142
128
|
# Get list of records for a given model class.
|
143
129
|
#----------------------------------------------------------------------------
|
144
|
-
def get_list_of_records(
|
145
|
-
items = klass.name.tableize
|
130
|
+
def get_list_of_records(options = {})
|
146
131
|
options[:query] ||= params[:query] if params[:query]
|
147
132
|
self.current_page = options[:page] if options[:page]
|
148
133
|
query, tags = parse_query_and_tags(options[:query]) if options[:query]
|
149
134
|
self.current_query = query
|
150
135
|
|
151
|
-
|
152
|
-
|
153
|
-
:order => current_user.pref[:"#{items}_sort_by"] || klass.sort_by
|
154
|
-
}
|
136
|
+
order = current_user.pref[:"#{controller_name}_sort_by"] || klass.sort_by
|
137
|
+
|
155
138
|
pages = {
|
156
139
|
:page => current_page,
|
157
|
-
:per_page => current_user.pref[:"#{
|
140
|
+
:per_page => current_user.pref[:"#{controller_name}_per_page"]
|
158
141
|
}
|
159
142
|
|
160
|
-
# Call the hook and return its output if any.
|
161
|
-
assets = hook(:"get_#{items}", self, :records => records, :pages => pages)
|
162
|
-
return assets.last unless assets.empty?
|
163
|
-
|
164
143
|
# Use default processing if no hooks are present. Note that comma-delimited
|
165
144
|
# export includes deleted records, and the pagination is enabled only for
|
166
145
|
# plain HTTP, Ajax and XML API requests.
|
167
146
|
wants = request.format
|
168
|
-
filter = session[
|
147
|
+
filter = session[:"#{controller_name}_filter"].to_s.split(',')
|
169
148
|
|
170
|
-
scope =
|
171
|
-
scope = scope.merge(search.result)
|
149
|
+
scope = entities.merge(search.result)
|
172
150
|
scope = scope.state(filter) if filter.present?
|
173
151
|
scope = scope.text_search(query) if query.present?
|
174
152
|
scope = scope.tagged_with(tags, :on => :tags) if tags.present?
|
175
|
-
scope = scope.
|
153
|
+
scope = scope.order(order)
|
176
154
|
scope = scope.paginate(pages) if wants.html? || wants.js? || wants.xml?
|
177
155
|
scope
|
178
156
|
end
|
179
157
|
|
180
158
|
#----------------------------------------------------------------------------
|
181
159
|
def update_recently_viewed
|
182
|
-
|
183
|
-
|
160
|
+
entity.versions.create(:event => :view, :whodunnit => PaperTrail.whodunnit)
|
161
|
+
end
|
162
|
+
|
163
|
+
#----------------------------------------------------------------------------
|
164
|
+
def field_group
|
165
|
+
if @tag = Tag.find_by_name(params[:tag].strip)
|
166
|
+
if @field_group = FieldGroup.find_by_tag_id_and_klass_name(@tag.id, klass.to_s)
|
167
|
+
@asset = klass.find_by_id(params[:asset_id]) || klass.new
|
168
|
+
render 'fields/group' and return
|
169
|
+
end
|
170
|
+
end
|
171
|
+
render :text => ''
|
172
|
+
end
|
173
|
+
|
174
|
+
# Somewhat simplistic parser that extracts query and hash-prefixed tags from
|
175
|
+
# the search string and returns them as two element array, for example:
|
176
|
+
#
|
177
|
+
# "#real Billy Bones #pirate" => [ "Billy Bones", "real, pirate" ]
|
178
|
+
#----------------------------------------------------------------------------
|
179
|
+
def parse_query_and_tags(search_string)
|
180
|
+
query, tags = [], []
|
181
|
+
search_string.scan(/[\w@\-\.#]+/).each do |token|
|
182
|
+
if token.starts_with?("#")
|
183
|
+
tags << token[1 .. -1]
|
184
|
+
else
|
185
|
+
query << token
|
186
|
+
end
|
184
187
|
end
|
188
|
+
[ query.join(" "), tags.join(", ") ]
|
189
|
+
end
|
190
|
+
|
191
|
+
#----------------------------------------------------------------------------
|
192
|
+
def timeline(asset)
|
193
|
+
(asset.comments + asset.emails).sort { |x, y| y.created_at <=> x.created_at }
|
185
194
|
end
|
186
195
|
end
|