diff --git a/app/assets/javascripts/attachments.js.coffee b/app/assets/javascripts/attachments.js.coffee
index db6fc07..e9dfc1e 100644
--- a/app/assets/javascripts/attachments.js.coffee
+++ b/app/assets/javascripts/attachments.js.coffee
@@ -7,7 +7,8 @@ jQuery ->
data:
'_method': 'put',
'attachment[col_sep]': $('#attachment_col_sep').val(),
- 'attachment[quote_char]': $("#attachment_quote_char").val()
+ 'attachment[quote_char]': $("#attachment_quote_char").val(),
+ 'attachment[encoding]': $("#attachment_encoding").val()
,
success: (data) -> insertFields(data)
false
@@ -24,6 +25,7 @@ jQuery ->
authenticity_token: $("input[name='authenticity_token']").val()
col_sep: $("#attachment_col_sep").val()
quote_char: $("#attachment_quote_char").val()
+ encoding: $("#attachment_encoding").val()
,
onComplete: (id, fileName, data) ->
insertFields(data)
diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css
index 07157e4..91ee4ff 100644
--- a/app/assets/stylesheets/application.css
+++ b/app/assets/stylesheets/application.css
@@ -14,3 +14,4 @@ ul.top_menu li:first-child a{margin-left:0}
ul.top_menu li:last-child{border-right:none}
hr.seperator{border-top:1px solid #ccc;background:#ccc;margin:5px 0}
.clear{clear:both}
+form label span.required{color: red; font-size: 110%; margin-left: 4px;}
diff --git a/app/controllers/attachments_controller.rb b/app/controllers/attachments_controller.rb
index 171fdf9..e855a1e 100644
--- a/app/controllers/attachments_controller.rb
+++ b/app/controllers/attachments_controller.rb
@@ -2,7 +2,7 @@ class AttachmentsController < ApplicationController
load_and_authorize_resource
def new
- @attachment = Attachment.new(col_sep: ',', quote_char: '"')
+ @attachment = Attachment.new(col_sep: ',', quote_char: '"', encoding: 'utf-8')
end
# TODO:
@@ -11,7 +11,7 @@ def new
# - find or construct a row with all data set, so we can show examples
def create
# puts params[:file].tempfile.external_encoding.name
- @attachment = Attachment.new(uploaded_data: params[:file], col_sep: params[:col_sep], quote_char: params[:quote_char])
+ @attachment = Attachment.new(uploaded_data: params[:file], col_sep: params[:col_sep], quote_char: params[:quote_char], encoding: params[:encoding])
@attachment.user = current_user
@attachment.save!
render json: {success: true, id: @attachment.id, rows: @attachment.rows(4)}, status: :ok
@@ -20,7 +20,8 @@ def create
def update
if @attachment.update_attributes(params[:attachment])
respond_to do |format|
- format.html { redirect_to new_attachment_mapping_url(@attachment) }
+ format.html { redirect_to (@attachment.mapping.blank? ? new_attachment_mapping_url(@attachment) : new_attachment_import_url(@attachment))
+ }
format.js { render json: {rows: @attachment.rows(4)}, status: :ok }
end
else
diff --git a/app/helpers/mappings_helper.rb b/app/helpers/mappings_helper.rb
new file mode 100644
index 0000000..c1f5664
--- /dev/null
+++ b/app/helpers/mappings_helper.rb
@@ -0,0 +1,5 @@
+module MappingsHelper
+ def mapping_options
+ Mapping.by_company(session['company_id']).with_fields.map{|m| [m.title, m.id]}
+ end
+end
diff --git a/app/models/attachment.rb b/app/models/attachment.rb
index 6295120..94ca25f 100644
--- a/app/models/attachment.rb
+++ b/app/models/attachment.rb
@@ -20,9 +20,9 @@ class Attachment < ActiveRecord::Base
after_destroy :delete_file
validates :filename, :disk_filename, presence: true
- validates :col_sep, :quote_char, presence: true
+ validates :col_sep, :quote_char, :encoding, presence: true
- attr_accessible :col_sep, :quote_char, :uploaded_data
+ attr_accessible :col_sep, :quote_char, :uploaded_data, :encoding, :mapping_id
attr_reader :error_rows
# Any upload file gets passed in as uploaded_data attribute
@@ -53,8 +53,8 @@ def rows(size = 0)
# When parsing data, we expect our file to be saved as valid utf-8
def parsed_data
@parsed_data ||= begin
- CSV.read(full_filename, col_sep: col_sep, quote_char: quote_char)
- rescue CSV::MalformedCSVError => er
+ CSV.read(full_filename, col_sep: col_sep, quote_char: quote_char, encoding: encoding)
+ rescue #CSV::MalformedCSVError => er
rows = []
#one more attempt. If BOM is present in the file.
begin
diff --git a/app/models/mapping.rb b/app/models/mapping.rb
index a81b969..cd474ac 100644
--- a/app/models/mapping.rb
+++ b/app/models/mapping.rb
@@ -8,7 +8,12 @@ class Mapping < ActiveRecord::Base
default_scope order('mappings.id desc')
accepts_nested_attributes_for :mapping_elements
-
+ scope :by_company, lambda{|company_id| where(:company_id => company_id)}
+ scope :with_fields, joins(:mapping_elements).
+ select('mappings.id, count(mapping_elements.id) as element_count').
+ group('mappings.id').
+ having('element_count > 0')
+
def title
I18n.t('mappings.title', count: mapping_elements.count, fields: mapping_elements.collect(&:target).to_sentence)
end
diff --git a/app/views/attachments/new.html.haml b/app/views/attachments/new.html.haml
index 7dcf3e8..14529ff 100644
--- a/app/views/attachments/new.html.haml
+++ b/app/views/attachments/new.html.haml
@@ -10,13 +10,17 @@
= form_for @attachment, method: 'put' do |f|
.clearfix
- = label_tag :col_sep, Attachment.human_attribute_name(:col_sep)
+ = label_tag :col_sep, "#{Attachment.human_attribute_name(:col_sep)} *".html_safe
.input
= f.text_field :col_sep, class: 'minimi'
.clearfix
- = label_tag :quote_char, Attachment.human_attribute_name(:quote_char)
+ = label_tag :quote_char, "#{Attachment.human_attribute_name(:quote_charp)} *".html_safe
.input
= f.text_field :quote_char, class: 'minimi'
+ .clearfix
+ = label_tag :encoding, "#{Attachment.human_attribute_name(:encoding)} *".html_safe
+ .input
+ = f.text_field :encoding
- if @attachment.new_record?
.clearfix
%label=t(:'attachments.upload')
@@ -29,4 +33,4 @@
.actions
= f.submit t('attachments.proceed_to_mapping'), class: "btn primary large"
- = link_to t('link.back_to_list'), attachments_path, class: "btn secondary"
\ No newline at end of file
+ = link_to t('link.back_to_list'), attachments_path, class: "btn secondary"
diff --git a/app/views/mappings/new.html.haml b/app/views/mappings/new.html.haml
index ef4686f..6c1379a 100644
--- a/app/views/mappings/new.html.haml
+++ b/app/views/mappings/new.html.haml
@@ -1,6 +1,12 @@
%h2
= t('link.step', count: 2, total: 3)
= t('mappings.new')
+
+= form_for @attachment do |f|
+ %p= t('mappings.reuse')
+ = f.select 'mapping_id', options_for_select(mapping_options)
+ = f.submit t('mappings.proceed_to_import'), :class => "btn primary large"
+%hr
= form_for [@attachment, @mapping] do |f|
.clearfix
@@ -22,4 +28,4 @@
.target{attrs.merge('data-target' => name)}= name
.actions
= f.submit t('mappings.proceed_to_import'), :class => "btn primary large"
- = link_to t('link.back_to_list'), attachments_path, class: "btn secondary"
\ No newline at end of file
+ = link_to t('link.back_to_list'), attachments_path, class: "btn secondary"
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 9b200f8..055f9e0 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -35,7 +35,8 @@ en:
new: Upload new CSV file
upload: Upload
proceed_to_mapping: Proceed to mapping
- delete_confirm: "Please note that, this is irreversible process. This will delete associated imports. Are you sure?"
+ delete_confirm: "Please note that, this is irreversible process. This will delete associated imports. Are you sure?"
+ csv_import_error: "Try with different 'Column Separator' and/or 'Quote character'."
mappings:
title:
one: "%{count} field: %{fields}"
@@ -44,6 +45,7 @@ en:
proceed_to_import: Proceed to import
source_fields: Source fields
target_fields: Target fields
+ reuse: Select an existing mapping from the list to reuse that or create a new mapping in the below section.
dnd_info: "Please drag&drop fields above onto their targets below. Drop multiple fields on a target to join values (space-delimited) e.g for the tag list."
imports:
title_success:
diff --git a/db/migrate/20120213113143_add_encoding_to_attachments.rb b/db/migrate/20120213113143_add_encoding_to_attachments.rb
new file mode 100644
index 0000000..f781a29
--- /dev/null
+++ b/db/migrate/20120213113143_add_encoding_to_attachments.rb
@@ -0,0 +1,5 @@
+class AddEncodingToAttachments < ActiveRecord::Migration
+ def change
+ add_column :attachments, :encoding, :string
+ end
+end
diff --git a/spec/controllers/attachments_controller_spec.rb b/spec/controllers/attachments_controller_spec.rb
index 4685fff..cf6b55f 100644
--- a/spec/controllers/attachments_controller_spec.rb
+++ b/spec/controllers/attachments_controller_spec.rb
@@ -106,27 +106,27 @@
describe "POST #create" do
it "creates new attachment" do
lambda {
- post :create, file: file_upload('test1.csv'), col_sep: ';', quote_char: '"'
+ post :create, file: file_upload('test1.csv'), col_sep: ';', quote_char: '"', encoding: 'utf-8'
}.should change(Attachment, :count).by(1)
end
it "reveals new attachment" do
- post :create, file: file_upload('test1.csv'), col_sep: ';', quote_char: '"'
+ post :create, file: file_upload('test1.csv'), col_sep: ';', quote_char: '"', encoding: 'utf-8'
assigns[:attachment].should_not be_nil
end
it "sets attachment user_id" do
- post :create, file: file_upload('test1.csv'), col_sep: ';', quote_char: '"'
+ post :create, file: file_upload('test1.csv'), col_sep: ';', quote_char: '"', encoding: 'utf-8'
assigns[:attachment].user_id.should == @user_id
end
it "sets attachment company_id" do
- post :create, file: file_upload('test1.csv'), col_sep: ';', quote_char: '"'
+ post :create, file: file_upload('test1.csv'), col_sep: ';', quote_char: '"', encoding: 'utf-8'
assigns[:attachment].company_id.should == @company_id
end
it "renders successful json response" do
- post :create, file: file_upload('test1.csv'), col_sep: ';', quote_char: '"'
+ post :create, file: file_upload('test1.csv'), col_sep: ';', quote_char: '"', encoding: 'utf-8'
response.content_type.should == "application/json"
response.code.should == "200"
end
@@ -152,11 +152,16 @@
assigns[:attachment].quote_char.should == '^'
end
- it "redirects to new attachment mapping on html request" do
- put :update, id: @authorized_attachment, attachment: {col_sep: ';'}
+ it "redirects to new attachment mapping on html request if mapping is not set" do
+ put :update, id: @authorized_attachment, attachment: {col_sep: ';', mapping_id: ''}
response.should redirect_to(new_attachment_mapping_url(@authorized_attachment))
end
+ it "redirects to new attachment import on html request if mapping is set" do
+ mapping = Factory(:mapping)
+ put :update, id: @authorized_attachment, attachment: {col_sep: ';', mapping_id: mapping.id}
+ response.should redirect_to(new_attachment_import_url(@authorized_attachment))
+ end
it "reneders successful json response on js request" do
put :update, id: @authorized_attachment, attachment: {col_sep: ';'}, format: 'js'
response.code.should == "200"
diff --git a/spec/factories.rb b/spec/factories.rb
index a042805..6f0e140 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -3,6 +3,7 @@
uploaded_data { file_upload('test1.csv') }
col_sep ';'
quote_char '"'
+ encoding 'utf-8'
association :mapping
end
diff --git a/spec/models/attachment_spec.rb b/spec/models/attachment_spec.rb
index 374732e..db49605 100644
--- a/spec/models/attachment_spec.rb
+++ b/spec/models/attachment_spec.rb
@@ -3,7 +3,15 @@
describe Attachment do
it { should belong_to(:mapping) }
it { should have_many(:imports).dependent(:destroy) }
-
+
+ ['filename', 'col_sep', 'quote_char', 'encoding', 'disk_filename'].each do |attribute|
+ it { should validate_presence_of(attribute)}
+ end
+
+ [:col_sep, :quote_char, :uploaded_data, :encoding, :mapping_id].each do |attribute|
+ it { should allow_mass_assignment_of(attribute) }
+ end
+
before :each do
@attachment = Factory(:attachment)
end
diff --git a/spec/models/mapping_spec.rb b/spec/models/mapping_spec.rb
index de00a9a..97c4e8b 100644
--- a/spec/models/mapping_spec.rb
+++ b/spec/models/mapping_spec.rb
@@ -1,6 +1,41 @@
require 'spec_helper'
describe Mapping do
+ before :each do
+ @mapping = Factory(:mapping, :company_id => 'a company')
+ Factory(:mapping_element, mapping: @mapping)
+ Factory(:gender_mapping_element, mapping: @mapping)
+ Factory(:birthday_mapping_element, mapping: @mapping)
+ end
+
it { should have_many(:mapping_elements).dependent(:destroy) }
it { should have_many(:attachments).dependent(:nullify) }
+
+ describe ".by_company" do
+ it "includes mappings belongs to company" do
+ Mapping.by_company('a company').should include(@mapping)
+ end
+
+ it "excludes mappings belongs to other company" do
+ another_mapping = Factory(:mapping, :company_id => 'another company')
+ Mapping.by_company('a company').should_not include(another_mapping)
+ end
+ end
+
+ describe ".with_fields" do
+ it "includes mappings with more than one mapping element defined" do
+ Mapping.with_fields.should include(@mapping)
+ end
+
+ it "excludes mappings belongs to other company" do
+ another_mapping = Factory(:mapping, :company_id => 'another company')
+ Mapping.with_fields.should_not include(another_mapping)
+ end
+ end
+
+ describe '#title' do
+ it 'should return mapping details' do
+ @mapping.title.should == '3 fields: organization, gender, and birthday'
+ end
+ end
end