e9_crm 0.1.13 → 0.1.14
Sign up to get free protection for your applications and to get access to all the features.
- data/app/controllers/e9_crm/campaign_subclass_controller.rb +2 -1
- data/app/controllers/e9_crm/contact_emails_controller.rb +1 -1
- data/app/controllers/e9_crm/dated_costs_controller.rb +32 -5
- data/app/controllers/e9_crm/leads_controller.rb +4 -3
- data/app/controllers/e9_crm/users_controller.rb +22 -0
- data/app/helpers/e9_crm/base_helper.rb +3 -3
- data/app/models/dated_cost.rb +4 -0
- data/app/models/deal.rb +18 -16
- data/app/models/email_template.rb +1 -3
- data/app/views/e9_crm/affiliate_campaigns/_form_inner.html.haml +1 -1
- data/app/views/e9_crm/companies/_form_inner.html.haml +2 -2
- data/app/views/e9_crm/contacts/_form_inner.html.haml +6 -6
- data/app/views/e9_crm/contacts/_index_sidebar.html.haml +5 -14
- data/app/views/e9_crm/contacts/_sidebar.html.haml +1 -0
- data/app/views/e9_crm/dated_costs/_form_inner.html.haml +1 -1
- data/app/views/e9_crm/dated_costs/index.html.haml +2 -2
- data/app/views/e9_crm/deals/_form_inner.html.haml +4 -5
- data/app/views/e9_crm/email_templates/_form_inner.html.haml +3 -3
- data/app/views/e9_crm/record_attributes/_user.html.haml +2 -2
- data/config/locales/en.yml +13 -5
- data/config/routes.rb +7 -0
- data/lib/e9_crm/rack/company_auto_completer.rb +30 -0
- data/lib/e9_crm/rack/contact_auto_completer.rb +42 -0
- data/lib/e9_crm/version.rb +1 -1
- data/lib/e9_crm.rb +10 -5
- data/lib/generators/e9_crm/templates/javascript.js +115 -2
- metadata +5 -2
@@ -9,12 +9,13 @@ class E9Crm::CampaignSubclassController < E9Crm::ResourcesController
|
|
9
9
|
end
|
10
10
|
|
11
11
|
protected
|
12
|
+
|
12
13
|
def parent_redirect_path
|
13
14
|
campaigns_path(:type => type_param)
|
14
15
|
end
|
15
16
|
|
16
17
|
def type_param
|
17
|
-
resource_class.name[/(.*)Campaign/, 1].underscore
|
18
|
+
resource_class.name[/(.*)Campaign/, 1].underscore rescue nil
|
18
19
|
end
|
19
20
|
|
20
21
|
def add_index_breadcrumb
|
@@ -20,7 +20,7 @@ class E9Crm::ContactEmailsController < E9Crm::ResourcesController
|
|
20
20
|
ContactEmail.new_from_template(template, :contact_ids => params[:uids])
|
21
21
|
end
|
22
22
|
|
23
|
-
object.from_email
|
23
|
+
object.from_email = object.from_email.presence || current_user.email
|
24
24
|
|
25
25
|
object.valid?
|
26
26
|
|
@@ -1,15 +1,21 @@
|
|
1
|
-
class E9Crm::DatedCostsController < E9Crm::
|
1
|
+
class E9Crm::DatedCostsController < E9Crm::ResourcesController
|
2
2
|
belongs_to :advertising_campaign, :optional => true
|
3
3
|
defaults :resource_class => DatedCost
|
4
4
|
include E9Rails::Controllers::Orderable
|
5
5
|
|
6
|
+
self.should_paginate_index = true
|
7
|
+
|
6
8
|
filter_access_to :bulk_create, :require => :create, :context => :admin
|
7
9
|
|
10
|
+
prepend_before_filter :association_chain
|
8
11
|
before_filter :add_breadcrumbs
|
9
12
|
before_filter :generate_temp_id, :only => :new
|
10
13
|
|
14
|
+
respond_to :json, :only => :new
|
15
|
+
|
11
16
|
def index
|
12
17
|
if params[:advertising_campaign_id]
|
18
|
+
@index_title = "Advertising Costs for #{parent.name}" if parent
|
13
19
|
index!
|
14
20
|
else
|
15
21
|
@advertising_campaigns = AdvertisingCampaign.all
|
@@ -17,6 +23,13 @@ class E9Crm::DatedCostsController < E9Crm::CampaignSubclassController
|
|
17
23
|
end
|
18
24
|
end
|
19
25
|
|
26
|
+
def new
|
27
|
+
new! do |format|
|
28
|
+
format.html
|
29
|
+
format.json { render :json => { :html => render_html_for_action } }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
20
33
|
def bulk_create
|
21
34
|
params[:id].zip(params[:cost]) do |id, cost|
|
22
35
|
DatedCost.create(
|
@@ -33,8 +46,16 @@ class E9Crm::DatedCostsController < E9Crm::CampaignSubclassController
|
|
33
46
|
|
34
47
|
protected
|
35
48
|
|
36
|
-
def
|
37
|
-
|
49
|
+
def render_html_for_action(action = nil)
|
50
|
+
action ||= params[:action]
|
51
|
+
|
52
|
+
html = nil
|
53
|
+
|
54
|
+
lookup_context.update_details(:formats => [Mime::HTML.to_sym]) do
|
55
|
+
html = render_to_string(action, :layout => false)
|
56
|
+
end
|
57
|
+
|
58
|
+
html
|
38
59
|
end
|
39
60
|
|
40
61
|
def default_ordered_on
|
@@ -45,11 +66,17 @@ class E9Crm::DatedCostsController < E9Crm::CampaignSubclassController
|
|
45
66
|
'ASC'
|
46
67
|
end
|
47
68
|
|
48
|
-
def
|
49
|
-
|
69
|
+
def add_index_breadcrumb
|
70
|
+
#association_chain
|
71
|
+
|
72
|
+
add_breadcrumb! Campaign.model_name.collection.titleize, campaigns_path
|
73
|
+
|
74
|
+
if parent
|
50
75
|
add_breadcrumb! parent.name, edit_advertising_campaign_path(parent)
|
51
76
|
end
|
77
|
+
end
|
52
78
|
|
79
|
+
def add_breadcrumbs
|
53
80
|
add_breadcrumb! e9_t(:index_title)
|
54
81
|
end
|
55
82
|
|
@@ -39,10 +39,11 @@ class E9Crm::LeadsController < ApplicationController
|
|
39
39
|
|
40
40
|
def build_resource
|
41
41
|
get_resource_ivar || set_resource_ivar(
|
42
|
+
# NOTE mailing list ids come from the form (to allow opt-outs)
|
42
43
|
Deal.leads.new((params[resource_instance_name] || {}).reverse_merge(
|
43
|
-
:user
|
44
|
-
:offer
|
45
|
-
:campaign
|
44
|
+
:user => current_user,
|
45
|
+
:offer => @offer,
|
46
|
+
:campaign => tracking_campaign
|
46
47
|
))
|
47
48
|
)
|
48
49
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class E9Crm::UsersController < ApplicationController
|
2
|
+
inherit_resources
|
3
|
+
|
4
|
+
respond_to :html, :except => :new
|
5
|
+
respond_to :json, :only => :new
|
6
|
+
|
7
|
+
def new
|
8
|
+
new! do |format|
|
9
|
+
format.json { render :json => resource }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def build_resource
|
16
|
+
get_resource_ivar || begin
|
17
|
+
user = User.new(params[resource_instance_name] || {})
|
18
|
+
user.valid?
|
19
|
+
set_resource_ivar(user)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -6,9 +6,9 @@ module E9Crm::BaseHelper
|
|
6
6
|
|
7
7
|
alias :k :kramdown
|
8
8
|
|
9
|
-
def help_tooltip(string)
|
9
|
+
def help_tooltip(string, data_title = nil)
|
10
10
|
return <<-HTML.strip.html_safe
|
11
|
-
<span class="help" rel="tooltip" title="#{CGI.escape_html(string)}">#{t(:inline_help_link)}</span>
|
11
|
+
<span class="help" rel="tooltip" #{data_title ? %Q[data-title="#{data_title}"] : nil } title="#{CGI.escape_html(string)}">#{t(:inline_help_link)}</span>
|
12
12
|
HTML
|
13
13
|
end
|
14
14
|
|
@@ -20,7 +20,7 @@ module E9Crm::BaseHelper
|
|
20
20
|
str = ''.html_safe
|
21
21
|
str.safe_concat resource_humanize(key)
|
22
22
|
str.safe_concat ' '
|
23
|
-
str.safe_concat help_tooltip(help_title)
|
23
|
+
str.safe_concat help_tooltip(help_title, options.delete(:header))
|
24
24
|
|
25
25
|
if form_or_id.respond_to?(:label)
|
26
26
|
form_or_id.label(key, str, options)
|
data/app/models/dated_cost.rb
CHANGED
data/app/models/deal.rb
CHANGED
@@ -46,7 +46,7 @@ class Deal < ActiveRecord::Base
|
|
46
46
|
|
47
47
|
# If a lead with no user, find the user by email or create it, then if mailing_lists
|
48
48
|
# were passed, assign the user those mailing lists
|
49
|
-
after_create :
|
49
|
+
after_create :handle_user_if_lead
|
50
50
|
|
51
51
|
# money column definitions for pseudo attributes (added on the reports scope)
|
52
52
|
%w(total_value average_value total_cost average_cost).each do |money_column|
|
@@ -55,6 +55,8 @@ class Deal < ActiveRecord::Base
|
|
55
55
|
|
56
56
|
delegate :name, :to => :owner, :prefix => true, :allow_nil => true
|
57
57
|
|
58
|
+
# mailing_list_ids may be set on Deals when they are being created as leads, this is
|
59
|
+
# done via opt-in checkboxes on the form
|
58
60
|
attr_accessor :mailing_list_ids
|
59
61
|
|
60
62
|
#
|
@@ -230,21 +232,21 @@ class Deal < ActiveRecord::Base
|
|
230
232
|
end
|
231
233
|
end
|
232
234
|
|
233
|
-
def
|
234
|
-
if lead?
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
235
|
+
def handle_user_if_lead
|
236
|
+
if lead?
|
237
|
+
if user.blank? && lead_email
|
238
|
+
user = User.find_by_email(lead_email) || create_prospect
|
239
|
+
update_attribute(:user_id, u.id)
|
240
|
+
end
|
241
|
+
|
242
|
+
if user.present?
|
243
|
+
user.create_contact_if_missing!
|
244
|
+
self.contacts << user.contact
|
245
|
+
|
246
|
+
if @mailing_list_ids
|
247
|
+
user.mailing_list_ids |= @mailing_list_ids
|
248
|
+
end
|
249
|
+
end
|
248
250
|
end
|
249
251
|
end
|
250
252
|
|
@@ -5,9 +5,7 @@ class EmailTemplate < Email
|
|
5
5
|
# TODO the email class hierarchy needs a major refactoring, it's backwards and convoluted
|
6
6
|
before_save :generate_html_body_from_text_body
|
7
7
|
|
8
|
-
validates :
|
9
|
-
validates :subject, :presence => true
|
10
|
-
validates :from_email, :presence => true, :email => { :allow_blank => true }
|
8
|
+
validates :from_email, :email => { :allow_blank => true }
|
11
9
|
|
12
10
|
def as_json(options = {})
|
13
11
|
{}.tap do |hash|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
%fieldset
|
4
4
|
%legend= e9_t(:affiliate_information_legend, :scope => 'e9_crm.campaigns')
|
5
5
|
.field
|
6
|
-
= f.label :
|
6
|
+
= f.label :affiliate, :class => :req, :for => 'campaign_affiliate_id'
|
7
7
|
= f.collection_select :affiliate_id, Contact.affiliates.ordered.all, :id, :name, {:prompt => true}, :id => 'campaign_affiliate_id'
|
8
8
|
.field
|
9
9
|
= help_label f, :affiliate_fee
|
@@ -30,14 +30,14 @@
|
|
30
30
|
|
31
31
|
%fieldset.contact-contact-fields
|
32
32
|
%legend= e9_t(:form_legend_contact)
|
33
|
-
= render_record_attribute_form(:phone_number_attributes
|
34
|
-
= render_record_attribute_form(:instant_messaging_handle_attributes
|
35
|
-
= render_record_attribute_form(:website_attributes
|
36
|
-
= render_record_attribute_form(:address_attributes
|
33
|
+
= render_record_attribute_form(:phone_number_attributes, f)
|
34
|
+
= render_record_attribute_form(:instant_messaging_handle_attributes, f)
|
35
|
+
= render_record_attribute_form(:website_attributes, f)
|
36
|
+
= render_record_attribute_form(:address_attributes, f)
|
37
37
|
|
38
38
|
%fieldset.contact-background-info
|
39
|
-
%legend= f
|
40
|
-
.field
|
39
|
+
%legend= help_label(f, :info, :key => :markdown_help, :header => 'Markdown Help')
|
40
|
+
.field
|
41
41
|
= f.text_area :info
|
42
42
|
|
43
43
|
- content_for :bottom_javascripts do
|
@@ -2,22 +2,13 @@
|
|
2
2
|
= link_to_new_resource(Contact)
|
3
3
|
= link_to_collection(Company)
|
4
4
|
|
5
|
-
|
6
|
-
-#- etag, ntag = contact_email_template_select_tag, contact_newsletter_select_tag
|
7
|
-
-#- if [etag, ntag].any?(&:present?)
|
8
|
-
- if (etag = contact_newsletter_select_tag).present?
|
5
|
+
- if (etag = contact_email_template_select_tag).present?
|
9
6
|
%fieldset
|
10
7
|
%legend= e9_t(:email_actions_legend)
|
11
|
-
-
|
12
|
-
=
|
13
|
-
|
14
|
-
|
15
|
-
= submit_tag e9_t(:send_email_template), :name => nil
|
16
|
-
-#- if ntag
|
17
|
-
-#= form_tag send_email_admin_user_email_path('__ID__'), :method => :put, :id => 'contact_newsletter_form', 'data-confirm' => e9_t(:contact_newsletter_confirmation, :count => collection.length), 'data-empty' => e9_t(:no_contacts_notification), 'data-count' => @contact_ids.length do
|
18
|
-
-#= ntag
|
19
|
-
-#= hidden_field_tag 'uids', @contact_ids.join(','), :id => 'contact_newsletter_uids'
|
20
|
-
-#= submit_tag e9_t(:send_email_newsletter), :name => nil
|
8
|
+
= form_tag new_contact_email_path, :method => :get, :id => 'contact_email_form', 'data-empty' => e9_t(:no_contacts_notification), 'data-count' => @contact_ids.length do
|
9
|
+
= etag
|
10
|
+
= hidden_field_tag 'uids', @contact_ids.join(','), :id => 'contact_email_uids'
|
11
|
+
= submit_tag e9_t(:send_email_template), :name => nil
|
21
12
|
|
22
13
|
-# Search filter options
|
23
14
|
%fieldset
|
@@ -25,6 +25,7 @@
|
|
25
25
|
%label= Contact.human_attribute_name(:website_attributes)
|
26
26
|
- resource.website_attributes.each do |website_attribute|
|
27
27
|
.contact-website
|
28
|
+
- url = website_attribute.value =~/^\w+:\/\// ? website_attribute.value : "http://#{website_attribute.value}"
|
28
29
|
= link_to(website_attribute.to_s, website_attribute.to_s, :rel => "external nofollow")
|
29
30
|
|
30
31
|
- if resource.address_attributes.any?
|
@@ -6,7 +6,7 @@
|
|
6
6
|
- unless request.xhr?
|
7
7
|
= f.label :date, nil, :class => :req, :for => id
|
8
8
|
= f.text_field :date, :class => 'date-picker', :value => l(f.object.date), :id => id
|
9
|
-
.field
|
9
|
+
.field.cost
|
10
10
|
- fid = "dated_cost_cost_#{id}"
|
11
11
|
- unless request.xhr?
|
12
12
|
= f.label :cost, nil, :class => :req, :for => id
|
@@ -5,11 +5,11 @@
|
|
5
5
|
.dated-cost-labels
|
6
6
|
.field
|
7
7
|
= resource_class.human_attribute_name(:date)
|
8
|
-
.field
|
8
|
+
.field.cost
|
9
9
|
= resource_class.human_attribute_name(:cost)
|
10
10
|
|
11
11
|
= render collection
|
12
12
|
|
13
13
|
.actions
|
14
|
-
= link_to_new_resource(resource_class, :
|
14
|
+
= link_to_new_resource(resource_class, :class => 'new-resource')
|
15
15
|
|
@@ -22,14 +22,13 @@
|
|
22
22
|
= f.text_field :value
|
23
23
|
.field.select
|
24
24
|
= f.label :owner
|
25
|
-
= f.collection_select :contact_id, Contact.all, :id, :name, :prompt => true
|
25
|
+
= f.collection_select :contact_id, Contact.sales_persons.all, :id, :name, :prompt => true
|
26
26
|
.field.select
|
27
27
|
= f.label :contacts
|
28
|
-
%
|
29
|
-
= deal_contact_select_options
|
28
|
+
%input#contact_autocomplete.list{:type => 'text', 'data-values' => f.object.contact_ids.join(','), 'data-iname' => resource_instance_name, 'data-field' => '[contact_ids]'}
|
30
29
|
%ul.select
|
31
30
|
- f.object.contacts.each do |contact|
|
32
|
-
%li
|
33
|
-
%span= contact.name
|
31
|
+
%li.ui-state-default
|
32
|
+
%span.content= contact.name
|
34
33
|
%input{:type => :hidden, :name => "contact[contact_ids][]", :value => contact.id}
|
35
34
|
%a{:class => :remove, :title => "Remove", :alt => "Remove"} Remove
|
@@ -2,11 +2,11 @@
|
|
2
2
|
= f.label :name, nil, :class => :req
|
3
3
|
= f.text_field :name
|
4
4
|
.field
|
5
|
-
= f.label :from_email
|
5
|
+
= f.label :from_email
|
6
6
|
= f.text_field :from_email
|
7
7
|
.field
|
8
|
-
= f.label :subject
|
8
|
+
= f.label :subject
|
9
9
|
= f.text_field :subject
|
10
10
|
.field
|
11
|
-
= f.label :text_body
|
11
|
+
= f.label :text_body
|
12
12
|
= f.text_area :text_body
|
data/config/locales/en.yml
CHANGED
@@ -17,6 +17,11 @@ en:
|
|
17
17
|
add_record_attribute: Add
|
18
18
|
destroy_record_attribute: Remove
|
19
19
|
|
20
|
+
# activemodel translation looks to %{i18n_scope}.attributes.%{model_name}.%{attribute}
|
21
|
+
# then simply attributes.%{attribute}, dropping i18n_scope, e.g "activerecord"
|
22
|
+
attributes:
|
23
|
+
markdown_help: "You can style the text in this field using the Markdown syntax as follows:\n\nA line break is created by putting 2 spaces\n\nat the end of the line above and then a return.\n\nA paragraph is created by putting a blank line between the first paragraph and the second paragraph.\n\nThis is the start of the next paragraph.\n\n*italics*\n\n**bold**\n\n***bold and italic text***\n\n* Item in a bulleted list\n\t* A sub-item, indented with 4 spaces\n* Another item in a bulleted list\n\n1. Item in numbered list\n2. Another Item in numbered list\n3. Another Item in numbered list\n\n# First-level heading\n\n## Second-level heading\n\n### Third-level heading\n\n#### Fourth-level heading\n\n> This is a blockquote.\n> Blockquote with hard wrap\n>\n> This is the second paragraph in the blockquote.\n>\n> ## This is an H2 in a blockquote\n\n[This is a link](http://www.google.com \"Google\")\n\n![Image Alt Text](image url \"Image Title\")\n\n--- Horizontal rules are created by 3 hyphens\n\nIf you need to actually render the following characters AND they are NOT rendering, place a backslash before the character like \*italics\* will actually render with the asterisks instead of italicizing the word.\n\n\\\tbackslash\n*\tasterisk\n_\tunderscore\n{}\tcurly braces\n[]\tsquare brackets\n()\tparentheses\n#\thash mark\n+\tplus sign\n-\tminus sign (hyphen)\n.\tdot\n!\texclamation mark"
|
24
|
+
|
20
25
|
activerecord:
|
21
26
|
titles:
|
22
27
|
show: 'Show %{model}'
|
@@ -24,10 +29,12 @@ en:
|
|
24
29
|
show: '%{model}'
|
25
30
|
|
26
31
|
links:
|
27
|
-
edit: "Edit %{model}"
|
28
|
-
destroy: "Delete %{model}"
|
29
|
-
show: "View %{model}"
|
30
32
|
index: "Manage %{models}"
|
33
|
+
new: "New %{model}"
|
34
|
+
edit: "Edit"
|
35
|
+
destroy: "Delete"
|
36
|
+
show: "View"
|
37
|
+
confirm_destroy: Are you sure? This cannot be undone.
|
31
38
|
|
32
39
|
campaign_group:
|
33
40
|
confirm_destroy: Are you sure? This cannot be undone. Any campaigns which are associated with this group will become groupless.
|
@@ -108,8 +115,8 @@ en:
|
|
108
115
|
info: Background Information
|
109
116
|
not_ok_to_email: "This contact will not receive bulk email."
|
110
117
|
tag_instructions: "Tags are words or phrases that describe or categorize this contact.\n\nWhen searching a particular tag, the system will show all contacts with that tag."
|
111
|
-
no_deals: There are no deals associated with this contact.
|
112
|
-
no_leads: There are no leads associated with this contact.
|
118
|
+
no_deals: 'There are no deals associated with this contact.'
|
119
|
+
no_leads: 'There are no leads associated with this contact.'
|
113
120
|
company:
|
114
121
|
info: Background Information
|
115
122
|
deal:
|
@@ -119,6 +126,7 @@ en:
|
|
119
126
|
campaign_code: Code
|
120
127
|
offer_name: Offer
|
121
128
|
created_at: Date
|
129
|
+
owner: Responsible
|
122
130
|
offer:
|
123
131
|
template: Teaser Text
|
124
132
|
alert_email_instructions: (Enter an email if you want to be notified of conversions)
|
data/config/routes.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
Rails.application.routes.draw do
|
2
2
|
crm_path = 'admin/crm'
|
3
3
|
|
4
|
+
get '/autocomplete/contacts' => E9Crm::Rack::ContactAutoCompleter
|
5
|
+
get '/autocomplete/companies' => E9Crm::Rack::CompanyAutoCompleter
|
6
|
+
|
4
7
|
scope :module => :e9_crm do
|
5
8
|
resources :offers, :as => :public_offer, :only => :show do
|
6
9
|
resources :leads, :as => :deals, :only => [:new, :create], :path => ''
|
@@ -8,6 +11,10 @@ Rails.application.routes.draw do
|
|
8
11
|
end
|
9
12
|
|
10
13
|
scope :path => crm_path, :module => :e9_crm do
|
14
|
+
# NOTE this should be handled by base, and is here because base doesn't have a sensible
|
15
|
+
# user api, which crm needs to check for email uniqueness errors
|
16
|
+
resources :users, :only => :new
|
17
|
+
|
11
18
|
resources :companies, :except => :show
|
12
19
|
resources :contacts do
|
13
20
|
# page_views currently not routed, but near working
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module E9Crm::Rack
|
2
|
+
#
|
3
|
+
# Returns contacts and joins their primary user for their email if it exists,
|
4
|
+
# and will return a string like "firstname lastname (email)". If for whatever
|
5
|
+
# reason the contact has no primary user, it will drop the email.
|
6
|
+
#
|
7
|
+
class CompanyAutoCompleter
|
8
|
+
DEFAULT_LIMIT = 10
|
9
|
+
|
10
|
+
def self.call(env)
|
11
|
+
if env["PATH_INFO"] =~ /^\/autocomplete\/companies/
|
12
|
+
params = Rack::Request.new(env).params
|
13
|
+
|
14
|
+
if term = params['term']
|
15
|
+
relation = Company.limit(params['limit'] || DEFAULT_LIMIT).select('name').attr_like('name', term, :matcher => '%s%%')
|
16
|
+
|
17
|
+
companies = ::ActiveRecord::Base.connection.send(:select, relation.to_sql, 'Company Autocomplete').map do |row|
|
18
|
+
{ :label => row['name'], :value => row['name'] }
|
19
|
+
end
|
20
|
+
else
|
21
|
+
companies = []
|
22
|
+
end
|
23
|
+
|
24
|
+
[200, {"Content-Type" => "application/json", "Cache-Control" => "max-age=3600, must-revalidate"}, [companies.to_json]]
|
25
|
+
else
|
26
|
+
[404, {"Content-Type" => "text/html", "X-Cascade" => "pass"}, ["Not Found"]]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module E9Crm::Rack
|
2
|
+
#
|
3
|
+
# Returns contacts and joins their primary user for their email if it exists,
|
4
|
+
# and will return a string like "firstname lastname (email)". If for whatever
|
5
|
+
# reason the contact has no primary user, it will drop the email.
|
6
|
+
#
|
7
|
+
class ContactAutoCompleter
|
8
|
+
DEFAULT_LIMIT = 10
|
9
|
+
|
10
|
+
def self.call(env)
|
11
|
+
if env["PATH_INFO"] =~ /^\/autocomplete\/contacts/
|
12
|
+
params = Rack::Request.new(env).params
|
13
|
+
|
14
|
+
if query = params['query']
|
15
|
+
relation =
|
16
|
+
Contact.any_attrs_like('first_name', 'last_name', query).
|
17
|
+
limit(params['limit'] || DEFAULT_LIMIT).
|
18
|
+
joins("LEFT JOIN users on users.contact_id = contacts.id").
|
19
|
+
where(%{users.options REGEXP "primary: [\\"']?true" OR users.options IS NULL}).
|
20
|
+
select('contacts.id id, contacts.first_name first_name, contacts.last_name last_name, users.email email').
|
21
|
+
order('contacts.first_name ASC')
|
22
|
+
|
23
|
+
if params['except'] && (except = params['except'].scan(/(\d+),?/)) && !except.empty?
|
24
|
+
relation = relation.where( Contact.arel_table[:id].not_in(except.flatten) )
|
25
|
+
end
|
26
|
+
|
27
|
+
contacts = ::ActiveRecord::Base.connection.send(:select, relation.to_sql, 'Contact Autocomplete').map do |row|
|
28
|
+
name = row.values_at('first_name', 'last_name').join(' ').strip
|
29
|
+
name << " (#{row['email']})" if row['email']
|
30
|
+
{ :label => name, :value => name, :id => row['id'] }
|
31
|
+
end
|
32
|
+
else
|
33
|
+
contacts = []
|
34
|
+
end
|
35
|
+
|
36
|
+
[200, {"Content-Type" => "application/json", "Cache-Control" => "max-age=3600, must-revalidate"}, [contacts.to_json]]
|
37
|
+
else
|
38
|
+
[404, {"Content-Type" => "text/html", "X-Cascade" => "pass"}, ["Not Found"]]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/e9_crm/version.rb
CHANGED
data/lib/e9_crm.rb
CHANGED
@@ -11,11 +11,16 @@ require 'e9_base'
|
|
11
11
|
require 'e9_crm/rails_extensions'
|
12
12
|
|
13
13
|
module E9Crm
|
14
|
-
autoload :VERSION,
|
15
|
-
autoload :Controller,
|
16
|
-
autoload :Model,
|
17
|
-
autoload :Email,
|
18
|
-
autoload :TrackingController,
|
14
|
+
autoload :VERSION, 'e9_crm/version'
|
15
|
+
autoload :Controller, 'e9_crm/controller'
|
16
|
+
autoload :Model, 'e9_crm/model'
|
17
|
+
autoload :Email, 'e9_crm/email'
|
18
|
+
autoload :TrackingController, 'e9_crm/tracking_controller'
|
19
|
+
|
20
|
+
module Rack
|
21
|
+
autoload :ContactAutoCompleter, 'e9_crm/rack/contact_auto_completer'
|
22
|
+
autoload :CompanyAutoCompleter, 'e9_crm/rack/company_auto_completer'
|
23
|
+
end
|
19
24
|
|
20
25
|
mattr_accessor :cookie_name
|
21
26
|
@@cookie_name = '_e9_tc'
|
@@ -19,8 +19,19 @@
|
|
19
19
|
/*
|
20
20
|
*
|
21
21
|
*/
|
22
|
-
$('.dated-costs
|
23
|
-
|
22
|
+
$('.dated-costs a.new-resource').click(function(e) {
|
23
|
+
e.preventDefault();
|
24
|
+
|
25
|
+
var $this = $(this);
|
26
|
+
|
27
|
+
$.ajax({
|
28
|
+
url: $this.attr('href'),
|
29
|
+
dataType: 'json',
|
30
|
+
success: function(data) {
|
31
|
+
$(data.html).insertBefore($this.closest('.actions'));
|
32
|
+
}
|
33
|
+
});
|
34
|
+
|
24
35
|
});
|
25
36
|
|
26
37
|
$("#campaign_code_field input").keyup(function() {
|
@@ -130,6 +141,8 @@
|
|
130
141
|
|
131
142
|
|
132
143
|
$('#contact_email_form', $selector).live('submit', function(e) {
|
144
|
+
e.preventDefault();
|
145
|
+
|
133
146
|
var $f = $(this);
|
134
147
|
|
135
148
|
if ($f.attr('data-count') == '0') {
|
@@ -137,6 +150,15 @@
|
|
137
150
|
$f.undisable();
|
138
151
|
return false;
|
139
152
|
}
|
153
|
+
|
154
|
+
$.ajax({
|
155
|
+
url: $f.attr('action'),
|
156
|
+
data: $f.serializeArray(),
|
157
|
+
type: 'get',
|
158
|
+
success: function(data) {
|
159
|
+
$.colorbox({ html: data });
|
160
|
+
}
|
161
|
+
});
|
140
162
|
});
|
141
163
|
|
142
164
|
//$('#contact_newsletter_form', $selector).live('submit', function(e) {
|
@@ -298,4 +320,95 @@
|
|
298
320
|
}
|
299
321
|
});
|
300
322
|
});
|
323
|
+
|
324
|
+
|
325
|
+
function doNothing(e) {
|
326
|
+
var keyCode = event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;
|
327
|
+
|
328
|
+
alert(keyCode);
|
329
|
+
|
330
|
+
if( keyCode == 13 ) {
|
331
|
+
if(!e) var e = window.event;
|
332
|
+
|
333
|
+
e.cancelBubble = true;
|
334
|
+
e.returnValue = false;
|
335
|
+
|
336
|
+
if (e.stopPropagation) {
|
337
|
+
e.stopPropagation();
|
338
|
+
e.preventDefault();
|
339
|
+
}
|
340
|
+
}
|
341
|
+
}
|
342
|
+
|
343
|
+
/*
|
344
|
+
* Contact autocomplete
|
345
|
+
*/
|
346
|
+
var $contact_autocomplete = $('#contact_autocomplete');
|
347
|
+
//var search_cache = {};
|
348
|
+
|
349
|
+
$contact_autocomplete
|
350
|
+
// stop enter from submitting our form
|
351
|
+
.bind('keypress', function(e) {
|
352
|
+
if (e.keyCode == 13) e.preventDefault();
|
353
|
+
})
|
354
|
+
.autocomplete({
|
355
|
+
delay: 400,
|
356
|
+
|
357
|
+
// on select, add the template (code is in widgets.js) and
|
358
|
+
// clear the input field
|
359
|
+
select: function(e, ui) {
|
360
|
+
$contact_autocomplete
|
361
|
+
.add_select_template(ui.item.value, ui.item.id)
|
362
|
+
.val('');
|
363
|
+
|
364
|
+
// return false to prevent autocomplete from filling the field
|
365
|
+
return false;
|
366
|
+
},
|
367
|
+
source: function(request, response) {
|
368
|
+
|
369
|
+
var data = 'query=' + request.term,
|
370
|
+
excl = $contact_autocomplete.attr('data-values');
|
371
|
+
|
372
|
+
// add 'except' ids if they exist in values.
|
373
|
+
if (excl.length) data += '&except=' + excl;
|
374
|
+
|
375
|
+
$.ajax({
|
376
|
+
url: "/autocomplete/contacts",
|
377
|
+
dataType: "json",
|
378
|
+
data: data,
|
379
|
+
success: function(data) {
|
380
|
+
// caching code, not impl
|
381
|
+
//search_cache.term = request.term;
|
382
|
+
//search_cache.content = data;
|
383
|
+
response(data);
|
384
|
+
}
|
385
|
+
});
|
386
|
+
}
|
387
|
+
})
|
388
|
+
;
|
389
|
+
|
390
|
+
var $company_autocomplete = $('#contact_company_name');
|
391
|
+
|
392
|
+
$company_autocomplete
|
393
|
+
.autocomplete({
|
394
|
+
delay: 400,
|
395
|
+
focus: function(e, ui) {
|
396
|
+
$company_autocomplete.val(ui.item.value);
|
397
|
+
return false;
|
398
|
+
},
|
399
|
+
source: function(request, response) {
|
400
|
+
$.ajax({
|
401
|
+
url: "/autocomplete/companies",
|
402
|
+
dataType: "json",
|
403
|
+
data: request,
|
404
|
+
success: function(data) {
|
405
|
+
// caching code, not impl
|
406
|
+
//search_cache.term = request.term;
|
407
|
+
//search_cache.content = data;
|
408
|
+
response(data);
|
409
|
+
}
|
410
|
+
});
|
411
|
+
}
|
412
|
+
})
|
413
|
+
;
|
301
414
|
});
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: e9_crm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.1.
|
5
|
+
version: 0.1.14
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Travis Cox
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-06-07 00:00:00 -04:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -170,6 +170,7 @@ files:
|
|
170
170
|
- app/controllers/e9_crm/page_views_controller.rb
|
171
171
|
- app/controllers/e9_crm/resources_controller.rb
|
172
172
|
- app/controllers/e9_crm/sales_campaigns_controller.rb
|
173
|
+
- app/controllers/e9_crm/users_controller.rb
|
173
174
|
- app/controllers/e9_crm/video_offers_controller.rb
|
174
175
|
- app/helpers/e9_crm/base_helper.rb
|
175
176
|
- app/helpers/e9_crm/campaign_groups_helper.rb
|
@@ -319,6 +320,8 @@ files:
|
|
319
320
|
- lib/e9_crm/e9_extensions.rb
|
320
321
|
- lib/e9_crm/email.rb
|
321
322
|
- lib/e9_crm/model.rb
|
323
|
+
- lib/e9_crm/rack/company_auto_completer.rb
|
324
|
+
- lib/e9_crm/rack/contact_auto_completer.rb
|
322
325
|
- lib/e9_crm/rails_extensions.rb
|
323
326
|
- lib/e9_crm/tracking_controller.rb
|
324
327
|
- lib/e9_crm/version.rb
|