alchemy_crm 2.0.4.1 → 2.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,12 +1,10 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.8.7
4
3
  - 1.9.2
5
4
  - 1.9.3
6
- - ree
7
5
  branches:
8
6
  only:
9
7
  - 2.0-stable
10
8
  before_script:
11
- - "sh -c 'cd spec/dummy && RAILS_ENV=test bundle exec rake db:schema:load'"
9
+ - "sh -c 'cd spec/dummy; RAILS_ENV=test bundle exec rake db:setup'"
12
10
  script: "bundle exec rspec spec"
@@ -9,6 +9,7 @@ Gem::Specification.new do |gem|
9
9
  gem.summary = %q{A fully featured CRM / Newsletter and Mailings Module for Alchemy CMS.}
10
10
  gem.homepage = "http://alchemy-cms.com"
11
11
  gem.license = 'BSD New'
12
+ gem.required_ruby_version = '>= 1.9.2'
12
13
 
13
14
  gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
14
15
  gem.files = `git ls-files`.split("\n")
@@ -19,7 +20,7 @@ Gem::Specification.new do |gem|
19
20
 
20
21
  gem.add_dependency 'alchemy_cms', ["~> 2.1.12"]
21
22
  gem.add_dependency 'vcard', ['~> 0.1.1']
22
- gem.add_dependency 'csv_magic', ['~> 0.2.2']
23
+ gem.add_dependency 'csv_magic', ['~> 0.2.3']
23
24
  gem.add_dependency 'delayed_job_active_record', ["~> 0.3.2"]
24
25
  gem.add_dependency 'acts-as-taggable-on', ['~> 2.1.0']
25
26
  gem.add_dependency 'rails3-jquery-autocomplete', ['~> 1.0.4']
@@ -40,8 +40,10 @@ module AlchemyCrm
40
40
  @contacts = @contacts.page(params[:page] || 1).per(per_page_value_for_screen_size)
41
41
  }
42
42
  format.csv {
43
- @columns = AlchemyCrm::Contact::EXPORTABLE_COLUMNS
44
- send_data render_to_string, :content_type => 'text/csv', :disposition => 'attachment', :filename => "contacts-#{Time.now.strftime('%Y-%m-%d_%H-%M')}.csv"
43
+ export_file_as(:csv)
44
+ }
45
+ format.xls {
46
+ export_file_as(:xls)
45
47
  }
46
48
  end
47
49
  end
@@ -68,9 +70,13 @@ module AlchemyCrm
68
70
  end
69
71
 
70
72
  def export
71
- @contact = Contact.find(params[:id])
72
- @contact.to_vcard
73
- send_file("#{Rails.root.to_s}/tmp/#{@contact.fullname}.vcf")
73
+ if params[:id].present?
74
+ @contact = Contact.find(params[:id])
75
+ @contact.to_vcard
76
+ send_file("#{Rails.root.to_s}/tmp/#{@contact.fullname}.vcf")
77
+ else
78
+ render :layout => false
79
+ end
74
80
  end
75
81
 
76
82
  def autocomplete_tag_list
@@ -133,6 +139,12 @@ module AlchemyCrm
133
139
  content.starts_with?("BEGIN:VCARD")
134
140
  end
135
141
 
142
+ def export_file_as(format)
143
+ @columns = AlchemyCrm::Contact::EXPORTABLE_COLUMNS
144
+ filename = "#{AlchemyCrm::Contact.model_name.human(:count => @contacts.count)}-#{Time.now.strftime('%Y-%m-%d_%H-%M')}"
145
+ send_data render_to_string, :type => format.to_sym, :filename => "#{filename}.#{format}"
146
+ end
147
+
136
148
  end
137
149
  end
138
150
  end
@@ -0,0 +1,32 @@
1
+ <div class="with_padding">
2
+ <p><%= alchemy_crm_t('Please choose format') %></p>
3
+ <table id="export_format">
4
+ <tr>
5
+ <td class="submit">
6
+ <%= link_to(
7
+ 'Excel',
8
+ alchemy_crm.admin_contacts_path(
9
+ :format => :xls,
10
+ :query => params[:query]
11
+ ),
12
+ :class => 'button'
13
+ ) %>
14
+ </td>
15
+ </tr>
16
+ <tr>
17
+ <td class="submit">
18
+ <%= link_to(
19
+ 'CSV',
20
+ alchemy_crm.admin_contacts_path(
21
+ :format => :csv,
22
+ :query => params[:query]
23
+ ),
24
+ :class => 'button'
25
+ ) %>
26
+ </td>
27
+ </tr>
28
+ </table>
29
+ </div>
30
+ <script type="text/javascript">
31
+ $('.button', '#export_format').on('click', Alchemy.closeCurrentWindow);
32
+ </script>
@@ -1,7 +1,17 @@
1
- <%- csv = CSV.generate(:col_sep => ";", :row_sep => "\r\n", :force_quotes => true) do |csv| -%>
2
- <%- csv << @columns.map { |h| ::I18n.t(h, :scope => 'activerecord.attributes.alchemy_crm/contact', :default => h.humanize) } -%>
3
- <%- @contacts.each do |contact| -%>
4
- <%- csv << @columns.map { |a| value = contact.send(a).to_s.strip; a == 'salutation' && !value.blank? ? ::I18n.t(value.to_sym, :scope => 'alchemy_crm.salutations', :default => value) : value } -%>
5
- <%- end -%>
6
- <%- end -%>
7
- <%=raw csv %>
1
+ <% csv = CSV.generate(:col_sep => ";", :row_sep => "\r\n", :force_quotes => true) do |csv| %>
2
+ <% csv << @columns.map { |h| AlchemyCrm::Contact.human_attribute_name(h) } %>
3
+ <% @contacts.each do |contact| %>
4
+ <%
5
+ csv << @columns.map do |a|
6
+ value = contact.send(a).to_s.strip
7
+ if a == 'salutation' && !value.blank?
8
+ ::I18n.t(value.to_sym, :scope => 'alchemy_crm.salutations', :default => value)
9
+ elsif !value.blank? && a == 'verified' || a == 'disabled'
10
+ alchemy_crm_t(value.to_sym)
11
+ else
12
+ value
13
+ end
14
+ end %>
15
+ <% end %>
16
+ <% end %>
17
+ <%= raw csv %>
@@ -33,10 +33,12 @@
33
33
  {
34
34
  :icon => :file_download,
35
35
  :label => alchemy_crm_t(:export_contacts),
36
- :url => alchemy_crm.admin_contacts_path(:format => :csv, :query => params[:query]),
36
+ :url => alchemy_crm.export_admin_contacts_path(:query => params[:query]),
37
37
  :title => alchemy_crm_t(:export_contacts),
38
- :overlay => false,
39
- :loading_indicator => false,
38
+ :overlay_options => {
39
+ :title => alchemy_crm_t(:export_contacts),
40
+ :size => '200x150'
41
+ },
40
42
  :if_permitted_to => [:index, :alchemy_crm_admin_contacts]
41
43
  }
42
44
  ]
@@ -0,0 +1,34 @@
1
+ <?xml version="1.0"?>
2
+ <Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
3
+ xmlns:o="urn:schemas-microsoft-com:office:office"
4
+ xmlns:x="urn:schemas-microsoft-com:office:excel"
5
+ xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
6
+ xmlns:html="http://www.w3.org/TR/REC-html40">
7
+ <Worksheet ss:Name="<%= AlchemyCrm::Contact.model_name.human(:count => @contacts.count) -%>">
8
+ <Table>
9
+ <Row>
10
+ <% @columns.each do |col| %>
11
+ <Cell>
12
+ <Data ss:Type="String"><%= AlchemyCrm::Contact.human_attribute_name(col) %></Data>
13
+ </Cell>
14
+ <% end %>
15
+ </Row>
16
+ <% @contacts.each do |contact| %>
17
+ <Row>
18
+ <% @columns.each do |col| %>
19
+ <% value = contact.send(col).to_s.strip %>
20
+ <Cell>
21
+ <% if col == 'salutation' && !value.blank? %>
22
+ <Data ss:Type="String"><%= ::I18n.t(value.to_sym, :scope => 'alchemy_crm.salutations', :default => value) %></Data>
23
+ <% elsif !value.blank? && (col == 'verified' || col == 'disabled') %>
24
+ <Data ss:Type="String"><%= alchemy_crm_t(value) %></Data>
25
+ <% else %>
26
+ <Data ss:Type="String"><%= value %></Data>
27
+ <% end %>
28
+ </Cell>
29
+ <% end %>
30
+ </Row>
31
+ <% end %>
32
+ </Table>
33
+ </Worksheet>
34
+ </Workbook>
@@ -0,0 +1 @@
1
+ Mime::Type.register "application/xls", :xls
@@ -53,6 +53,7 @@ de:
53
53
  errors_while_importing_contacts: 'Diese Kontakte konnten auf Grund von Fehlern nicht importiert werden:'
54
54
  export_contact: Kontakt exportieren
55
55
  export_contacts: Kontakte exportieren
56
+ 'false': ''
56
57
  fake_contact_attributes:
57
58
  firstname: Kim
58
59
  lastname: Muster
@@ -94,6 +95,7 @@ de:
94
95
  or_replace_it_with_an_existing_tag: 'Oder Sie ersetzen es durch ein vorhandenes Tag'
95
96
  please_check_highlighted_vcards_on_errors: "Bitte überprüfen Sie die markierten Visitenkarten auf Fehler."
96
97
  please_choose: 'Bitte wählen'
98
+ 'Please choose format': 'Bitte wählen Sie ein Format'
97
99
  please_confirm: Bitte bestätigen
98
100
  read_in_browser_notice: "Falls der Newsletter nicht richtig dargestellt wird, klicken Sie bitte %{link}."
99
101
  remove_filter: 'Filter entfernen'
@@ -125,16 +127,21 @@ de:
125
127
  signout_form:
126
128
  button_label: abbestellen
127
129
  statistics: Statistiken
130
+ tags_get_created_while_tagging_contacts: 'Tags werden automatisch erstellt, sobald Sie es bei einem Kontakt das erste mal verwenden.'
128
131
  this_mailing_has_not_been_delivered_yet: 'Dieses Mailing wurde noch nie versendet'
129
132
  this_list_shows_all_deliveries: Dies ist eine Liste aller Sendungen dieses Mailings
130
133
  total_recipients_count: Empfänger insgesamt
131
- tags_get_created_while_tagging_contacts: 'Tags werden automatisch erstellt, sobald Sie es bei einem Kontakt das erste mal verwenden.'
134
+ 'true': 'Ja'
132
135
  without: ohne
133
136
  you_can_rename_this_tag: "Sie können dieses Tag umbenennen"
134
137
  you_can_open_statistics_for_delivered_mailings: Für bereits versendete Mailings können Statistiken aufgerufen werden
135
138
  you_have_no_contact_groups_yet: 'Sie haben noch keine Empfänger Zielgruppen gebildet'
136
139
 
137
140
  activerecord:
141
+ models:
142
+ alchemy_crm/contact:
143
+ one: Kontakt
144
+ other: Kontakte
138
145
  attributes:
139
146
  acts_as_taggable_on/tag:
140
147
  contacts_count: Anzahl der Kontakte
@@ -13,6 +13,7 @@ en:
13
13
  csv_format: 'A comma seperated file (.csv) with a list of contacts'
14
14
  import_format_notice: 'You may import '
15
15
  invalid_file_type: 'Invalid file type: %{mime_type}'
16
+ 'false': ''
16
17
  text_interpolation_notice: "Tip: You can insert the contact's name with %{name}."
17
18
  mail_text_interpolation_notice: "Tip: You can insert the contact's name with %{name}. Please insert the confirmation link with %{link}."
18
19
  mandatory_fields: "*Mandatory"
@@ -30,6 +31,7 @@ en:
30
31
  button_label: subscribe
31
32
  signout_form:
32
33
  button_label: unsubscribe
34
+ 'true': 'Yes'
33
35
 
34
36
  activerecord:
35
37
  attributes:
@@ -43,6 +43,7 @@ AlchemyCrm::Engine.routes.draw do
43
43
  resources :contacts do
44
44
  collection do
45
45
  get :import
46
+ get :export
46
47
  get :autocomplete_tag_list
47
48
  post :import
48
49
  end
@@ -1,3 +1,3 @@
1
1
  module AlchemyCrm
2
- VERSION = "2.0.4.1"
2
+ VERSION = "2.0.5"
3
3
  end
@@ -5,7 +5,7 @@ module AlchemyCrm
5
5
 
6
6
  render_views
7
7
 
8
- describe 'csv rendering' do
8
+ describe 'exporting contacts' do
9
9
 
10
10
  let(:contact) { FactoryGirl.create(:contact) }
11
11
  let(:jane) { FactoryGirl.create(:contact, :salutation => 'ms', :firstname => 'Jane', :email => 'jane@doe.com') }
@@ -16,42 +16,90 @@ module AlchemyCrm
16
16
  contact
17
17
  end
18
18
 
19
- it "should return contacts as attached csv file" do
20
- get :index, :format => 'csv', :use_route => :alchemy_crm
21
- response.content_type.should == 'text/csv'
22
- response.headers['Content-Disposition'].should match /attachment/
23
- end
19
+ context "as csv file" do
24
20
 
25
- it "csv file should contain translated headers" do
26
- get :index, :format => 'csv', :use_route => :alchemy_crm
27
- response.body.should match /Firstname/
28
- end
21
+ it "should return contacts as attached csv file" do
22
+ get :index, :format => 'csv', :use_route => :alchemy_crm
23
+ response.content_type.should == 'text/csv'
24
+ response.headers['Content-Disposition'].should match /attachment/
25
+ end
29
26
 
30
- it "csv file should contain translated salutation" do
31
- get :index, :format => 'csv', :use_route => :alchemy_crm
32
- response.body.should match /Mr/
33
- end
27
+ it "file should contain translated headers" do
28
+ get :index, :format => 'csv', :use_route => :alchemy_crm
29
+ response.body.should match /Firstname/
30
+ end
34
31
 
35
- it "contacts shouldn't be paginated" do
36
- jane
37
- controller.stub!(:per_page_value_for_screen_size).and_return(1)
38
- get :index, :format => 'csv', :use_route => :alchemy_crm
39
- response.body.should match /Jane/
40
- end
32
+ it "file should contain translated salutation" do
33
+ get :index, :format => 'csv', :use_route => :alchemy_crm
34
+ response.body.should match /Mr/
35
+ end
36
+
37
+ it "contacts shouldn't be paginated" do
38
+ jane
39
+ controller.stub!(:per_page_value_for_screen_size).and_return(1)
40
+ get :index, :format => 'csv', :use_route => :alchemy_crm
41
+ response.body.should match /Jane/
42
+ end
43
+
44
+ it "filename should contain timestamp" do
45
+ get :index, :format => 'csv', :use_route => :alchemy_crm
46
+ response.headers['Content-Disposition'].should match /[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}/
47
+ end
48
+
49
+ context "with search query" do
50
+
51
+ before { jane }
52
+
53
+ it "should return only the matched contacts" do
54
+ get :index, :format => 'csv', :use_route => :alchemy_crm, :query => 'Jon'
55
+ response.body.should match /Jon/
56
+ response.body.should_not match /Jane/
57
+ end
58
+
59
+ end
41
60
 
42
- it "filename should contain timestamp" do
43
- get :index, :format => 'csv', :use_route => :alchemy_crm
44
- response.headers['Content-Disposition'].should match /[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}/
45
61
  end
46
62
 
47
- context "with search query" do
63
+ context "as xls file" do
64
+
65
+ it "should return contacts as attached xls file" do
66
+ get :index, :format => 'xls', :use_route => :alchemy_crm
67
+ response.content_type.should == 'application/xls'
68
+ response.headers['Content-Disposition'].should match /attachment/
69
+ end
70
+
71
+ it "file should contain translated headers" do
72
+ get :index, :format => 'xls', :use_route => :alchemy_crm
73
+ response.body.should match /Firstname/
74
+ end
75
+
76
+ it "file should contain translated salutation" do
77
+ get :index, :format => 'xls', :use_route => :alchemy_crm
78
+ response.body.should match /Mr/
79
+ end
80
+
81
+ it "contacts shouldn't be paginated" do
82
+ jane
83
+ controller.stub!(:per_page_value_for_screen_size).and_return(1)
84
+ get :index, :format => 'xls', :use_route => :alchemy_crm
85
+ response.body.should match /Jane/
86
+ end
87
+
88
+ it "filename should contain timestamp" do
89
+ get :index, :format => 'xls', :use_route => :alchemy_crm
90
+ response.headers['Content-Disposition'].should match /[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}/
91
+ end
92
+
93
+ context "with search query" do
94
+
95
+ before { jane }
48
96
 
49
- before { jane }
97
+ it "should return only the matched contacts" do
98
+ get :index, :format => 'xls', :use_route => :alchemy_crm, :query => 'Jon'
99
+ response.body.should match /Jon/
100
+ response.body.should_not match /Jane/
101
+ end
50
102
 
51
- it "should return only the matched contacts" do
52
- get :index, :format => 'csv', :use_route => :alchemy_crm, :query => 'Jon'
53
- response.body.should match /Jon/
54
- response.body.should_not match /Jane/
55
103
  end
56
104
 
57
105
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alchemy_crm
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.4.1
4
+ version: 2.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-14 00:00:00.000000000 Z
12
+ date: 2012-09-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: alchemy_cms
@@ -50,7 +50,7 @@ dependencies:
50
50
  requirements:
51
51
  - - ~>
52
52
  - !ruby/object:Gem::Version
53
- version: 0.2.2
53
+ version: 0.2.3
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
@@ -58,7 +58,7 @@ dependencies:
58
58
  requirements:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: 0.2.2
61
+ version: 0.2.3
62
62
  - !ruby/object:Gem::Dependency
63
63
  name: delayed_job_active_record
64
64
  requirement: !ruby/object:Gem::Requirement
@@ -252,10 +252,12 @@ files:
252
252
  - app/views/alchemy_crm/admin/contacts/_form.html.erb
253
253
  - app/views/alchemy_crm/admin/contacts/destroy.rjs
254
254
  - app/views/alchemy_crm/admin/contacts/edit.html.erb
255
+ - app/views/alchemy_crm/admin/contacts/export.html.erb
255
256
  - app/views/alchemy_crm/admin/contacts/import.html.erb
256
257
  - app/views/alchemy_crm/admin/contacts/import.js.erb
257
258
  - app/views/alchemy_crm/admin/contacts/index.csv.erb
258
259
  - app/views/alchemy_crm/admin/contacts/index.html.erb
260
+ - app/views/alchemy_crm/admin/contacts/index.xls.erb
259
261
  - app/views/alchemy_crm/admin/contacts/new.html.erb
260
262
  - app/views/alchemy_crm/admin/contacts/vcf_import_result.html.erb
261
263
  - app/views/alchemy_crm/admin/deliveries/_delivery.html.erb
@@ -305,6 +307,7 @@ files:
305
307
  - config/authorization_rules.rb
306
308
  - config/initializers/assets.rb
307
309
  - config/initializers/delayed_job.rb
310
+ - config/initializers/xls_mime_type.rb
308
311
  - config/locales/alchemy.de.yml
309
312
  - config/locales/alchemy.en.yml
310
313
  - config/locales/alchemy_crm.de.yml
@@ -418,10 +421,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
418
421
  requirements:
419
422
  - - ! '>='
420
423
  - !ruby/object:Gem::Version
421
- version: '0'
422
- segments:
423
- - 0
424
- hash: -3633263896018909153
424
+ version: 1.9.2
425
425
  required_rubygems_version: !ruby/object:Gem::Requirement
426
426
  none: false
427
427
  requirements:
@@ -430,7 +430,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
430
430
  version: '0'
431
431
  segments:
432
432
  - 0
433
- hash: -3633263896018909153
433
+ hash: 1068326471216601821
434
434
  requirements: []
435
435
  rubyforge_project:
436
436
  rubygems_version: 1.8.24