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.
@@ -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 ||= current_user.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::CampaignSubclassController
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 collection
37
- get_collection_ivar || set_collection_ivar(end_of_association_chain.all)
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 add_breadcrumbs
49
- if parent?
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 => current_user,
44
- :offer => @offer,
45
- :campaign => tracking_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)
@@ -12,6 +12,10 @@ class DatedCost < ActiveRecord::Base
12
12
 
13
13
  attr_accessor :temp_id
14
14
 
15
+ def self.default_scope
16
+ order('dated_costs.created_at ASC')
17
+ end
18
+
15
19
  def as_json(options={})
16
20
  {}.tap do |hash|
17
21
  hash[:id] = self.id
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 :find_or_create_user, :assign_user_mailing_lists, :add_user_contact
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 find_or_create_user
234
- if lead? && user.blank? && lead_email
235
- u = User.find_by_email(lead_email) || create_prospect
236
- update_attribute(:user_id, u.id)
237
- end
238
- end
239
-
240
- def add_user_contact
241
- user.create_contact_if_missing!
242
- self.contacts << user.contact
243
- end
244
-
245
- def assign_user_mailing_lists
246
- if @mailing_list_ids
247
- user.mailing_list_ids |= @mailing_list_ids
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 :text_body, :presence => true
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 :affilate, nil, :class => :req, :for => 'campaign_affiliate_id'
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
@@ -1,6 +1,6 @@
1
1
  .field
2
2
  = f.label :name, nil, :class => :req
3
3
  = f.text_field :name
4
- .field.tinymce
5
- = f.label :info
4
+ .field
5
+ = help_label(f, :info, :key => :markdown_help, :header => 'Markdown Help')
6
6
  = f.text_area :info
@@ -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 , 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)
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.label(:info)
40
- .field.tinymce
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
- -# Email actions (template, newsletter)
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
- - if etag
12
- = 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
13
- = etag
14
- = hidden_field_tag 'uids', @contact_ids.join(','), :id => 'contact_email_uids'
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, :remote => true)
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
- %select.list{'data-iname' => resource_instance_name, 'data-field' => '[contact_ids]'}
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, nil, :class => :req
5
+ = f.label :from_email
6
6
  = f.text_field :from_email
7
7
  .field
8
- = f.label :subject, nil, :class => :req
8
+ = f.label :subject
9
9
  = f.text_field :subject
10
10
  .field
11
- = f.label :text_body, nil, :class => :req
11
+ = f.label :text_body
12
12
  = f.text_area :text_body
@@ -7,8 +7,8 @@
7
7
  .field
8
8
  = f.object.email
9
9
  - else
10
- .field
11
- = f.email_field :email
10
+ .field.contact-email
11
+ = f.text_field :email
12
12
 
13
13
  = f.fields_for f.object.options do |ff|
14
14
  - if (types = User.email_types).present?
@@ -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
@@ -1,3 +1,3 @@
1
1
  module E9Crm
2
- VERSION = '0.1.13'
2
+ VERSION = '0.1.14'
3
3
  end
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, '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'
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 > .actions a').bind('ajax:success', function(e, data, status, xhr) {
23
- $(data).insertBefore($(this).closest('.actions'));
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.13
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-05-31 00:00:00 -04:00
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