e9_crm 0.1.13 → 0.1.14
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.
- 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\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
|