diff --git a/Gemfile b/Gemfile
index cae686400..75fadeeee 100644
--- a/Gemfile
+++ b/Gemfile
@@ -46,7 +46,7 @@ gem 'ajax-datatables-rails', '~> 0.3.1'
gem 'commit_param_routing' # Enables different submit actions in the same form to route to different actions in controller
gem 'kaminari'
gem "i18n-js", ">= 3.0.0.rc11" # Localization in javascript files
-gem 'roo', '~> 2.1.0' # Spreadsheet parser
+gem 'roo', '~> 2.7.1' # Spreadsheet parser
gem 'wicked_pdf'
gem 'silencer' # Silence certain Rails logs
gem 'wkhtmltopdf-heroku'
diff --git a/Gemfile.lock b/Gemfile.lock
index 40a51e8f3..eb70da5f8 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -190,9 +190,8 @@ GEM
jquery-rails
rails (>= 3.2.0)
newrelic_rpm (4.0.0.332)
- nokogiri (1.6.8)
+ nokogiri (1.6.8.1)
mini_portile2 (~> 2.1.0)
- pkg-config (~> 1.1.7)
nokogumbo (1.4.10)
nokogiri
oj (2.17.4)
@@ -206,7 +205,6 @@ GEM
parser (2.4.0.0)
ast (~> 2.2)
pg (0.18.4)
- pkg-config (1.1.7)
polyglot (0.3.5)
powerpack (0.1.1)
puma (2.15.3)
@@ -257,7 +255,7 @@ GEM
algorithms (~> 0.6.1)
stream (~> 0.5.0)
rkelly-remix (0.0.7)
- roo (2.1.1)
+ roo (2.7.1)
nokogiri (~> 1)
rubyzip (~> 1.1, < 2.0.0)
rubocop (0.48.1)
@@ -268,7 +266,7 @@ GEM
unicode-display_width (~> 1.0, >= 1.0.1)
ruby-graphviz (1.2.2)
ruby-progressbar (1.8.1)
- rubyzip (1.1.7)
+ rubyzip (1.2.1)
sanitize (4.4.0)
crass (~> 1.0.2)
nokogiri (>= 1.4.4)
@@ -390,7 +388,7 @@ DEPENDENCIES
recaptcha
remotipart (~> 1.2)
rgl
- roo (~> 2.1.0)
+ roo (~> 2.7.1)
rubocop
ruby-graphviz (~> 1.2)
rubyzip
diff --git a/app/assets/javascripts/repositories/index.js b/app/assets/javascripts/repositories/index.js
index d6150415e..3ff5474cf 100644
--- a/app/assets/javascripts/repositories/index.js
+++ b/app/assets/javascripts/repositories/index.js
@@ -26,6 +26,11 @@
});
repositoryRecordsImporter();
});
+ }).on('ajax:error', function(ev, data) {
+ $(this).find('.form-group').addClass('has-error');
+ $(this).find('.form-group').find('.help-block').remove();
+ $(this).find('.form-group').append("" +
+ data.responseJSON.message + '');
});
}
diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb
index ca41b2ed4..bb56e7938 100644
--- a/app/controllers/repositories_controller.rb
+++ b/app/controllers/repositories_controller.rb
@@ -184,27 +184,27 @@ class RepositoriesController < ApplicationController
def parse_sheet
repository = current_team.repositories.find_by_id(params[:id])
- parsed_file = ImportRepository::ParseRepository.new(
- file: params[:file],
- repository: repository,
- session: session
- )
- respond_to do |format|
- unless params[:file]
- repository_response(t('teams.parse_sheet.errors.no_file_selected'))
- return
- end
- begin
- if parsed_file.too_large?
- repository_response(t('general.file.size_exceeded',
- file_size: Constants::FILE_MAX_SIZE_MB))
- elsif parsed_file.empty?
- flash[:notice] = t('teams.parse_sheet.errors.empty_file')
- redirect_to back and return
- else
- @import_data = parsed_file.data
- if parsed_file.generated_temp_file?
+ unless params[:file]
+ repository_response(t('teams.parse_sheet.errors.no_file_selected'))
+ return
+ end
+ begin
+ parsed_file = ImportRepository::ParseRepository.new(
+ file: params[:file],
+ repository: repository,
+ session: session
+ )
+ if parsed_file.too_large?
+ repository_response(t('general.file.size_exceeded',
+ file_size: Constants::FILE_MAX_SIZE_MB))
+ elsif parsed_file.empty?
+ flash[:notice] = t('teams.parse_sheet.errors.empty_file')
+ redirect_to back and return
+ else
+ @import_data = parsed_file.data
+ if parsed_file.generated_temp_file?
+ respond_to do |format|
format.json do
render json: {
html: render_to_string(
@@ -212,16 +212,16 @@ class RepositoriesController < ApplicationController
)
}
end
- else
- repository_response(t('teams.parse_sheet.errors.temp_file_failure'))
end
+ else
+ repository_response(t('teams.parse_sheet.errors.temp_file_failure'))
end
- rescue ArgumentError, CSV::MalformedCSVError
- repository_response(t('teams.parse_sheet.errors.invalid_file',
- encoding: ''.encoding))
- rescue TypeError
- repository_response(t('teams.parse_sheet.errors.invalid_extension'))
end
+ rescue ArgumentError, CSV::MalformedCSVError
+ repository_response(t('teams.parse_sheet.errors.invalid_file',
+ encoding: ''.encoding))
+ rescue TypeError
+ repository_response(t('teams.parse_sheet.errors.invalid_extension'))
end
end
@@ -238,8 +238,9 @@ class RepositoriesController < ApplicationController
number_of_rows: status[:nr_of_added])
render json: {}, status: :ok
else
- flash[:alert] = t('repositories.import_records.error_flash',
- message: status[:errors])
+ flash[:alert] =
+ t('repositories.import_records.partial_success_flash',
+ nr: status[:nr_of_added], total_nr: status[:total_nr])
render json: {}, status: :unprocessable_entity
end
else
@@ -320,13 +321,15 @@ class RepositoriesController < ApplicationController
end
def repository_response(message)
- format.html do
- flash[:alert] = message
- redirect_to :back
- end
- format.json do
- render json: { message: message },
- status: :unprocessable_entity
+ respond_to do |format|
+ format.html do
+ flash[:alert] = message
+ redirect_to :back
+ end
+ format.json do
+ render json: { message: message },
+ status: :unprocessable_entity
+ end
end
end
diff --git a/app/controllers/teams_controller.rb b/app/controllers/teams_controller.rb
index 244128f11..622cff038 100644
--- a/app/controllers/teams_controller.rb
+++ b/app/controllers/teams_controller.rb
@@ -36,8 +36,7 @@ class TeamsController < ApplicationController
# Get data (it will trigger any errors as well)
@header = sheet.row(1)
- @rows = [];
- @rows << Hash[[@header, sheet.row(2)].transpose]
+ @columns = sheet.row(2)
# Fill in fields for dropdown
@available_fields = @team.get_available_sample_fields
diff --git a/app/models/repository.rb b/app/models/repository.rb
index e47e79501..0e6c193c3 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -109,9 +109,10 @@ class Repository < ActiveRecord::Base
# Imports records
def import_records(sheet, mappings, user)
- errors = []
+ errors = false
custom_fields = []
name_index = -1
+ total_nr = 0
nr_of_added = 0
mappings.each.with_index do |(_k, value), index|
@@ -127,13 +128,17 @@ class Repository < ActiveRecord::Base
# Now we can iterate through record data and save stuff into db
(2..sheet.last_row).each do |i|
- error = []
+ total_nr += 1
+ cell_error = false
record_row = RepositoryRow.new(name: sheet.row(i)[name_index],
repository: self,
created_by: user,
last_modified_by: user)
- next unless record_row.valid?
+ unless record_row.valid?
+ errors = true
+ next
+ end
sheet.row(i).each.with_index do |value, index|
if custom_fields[index] && value
rep_column = RepositoryTextValue.new(
@@ -145,10 +150,11 @@ class Repository < ActiveRecord::Base
repository_column: custom_fields[index]
}
)
- error << rep_column.errors.messages unless rep_column.save
+ cell_error = true unless rep_column.save
end
end
- if error.any?
+ if cell_error
+ errors = true
record_row.destroy
else
nr_of_added += 1
@@ -156,10 +162,12 @@ class Repository < ActiveRecord::Base
end
end
- if errors.count > 0
- return { status: :error, errors: errors, nr_of_added: nr_of_added }
+ if errors
+ return { status: :error,
+ nr_of_added: nr_of_added,
+ total_nr: total_nr }
end
- { status: :ok, nr_of_added: nr_of_added }
+ { status: :ok, nr_of_added: nr_of_added, total_nr: total_nr }
end
private
diff --git a/app/services/import_repository/parse_repository.rb b/app/services/import_repository/parse_repository.rb
index e40c91280..192f4b61e 100644
--- a/app/services/import_repository/parse_repository.rb
+++ b/app/services/import_repository/parse_repository.rb
@@ -11,15 +11,14 @@ module ImportRepository
def data
# Get data (it will trigger any errors as well)
header = @sheet.row(1)
- rows = []
- rows << Hash[[header, @sheet.row(2)].transpose]
+ columns = @sheet.row(2)
# Fill in fields for dropdown
@repository.available_repository_fields.transform_values! do |name|
truncate(name, length: Constants::NAME_TRUNCATION_LENGTH_DROPDOWN)
end
@temp_file = TempFile.create(session_id: @session.id, file: @file)
Data.new(header,
- rows,
+ columns,
@repository.available_repository_fields,
@repository,
@temp_file)
@@ -47,7 +46,7 @@ module ImportRepository
end
Data = Struct.new(
- :header, :rows, :available_fields, :repository, :temp_file
+ :header, :columns, :available_fields, :repository, :temp_file
)
end
end
diff --git a/app/views/repositories/_parse_records_modal.html.erb b/app/views/repositories/_parse_records_modal.html.erb
index 05925e6c5..c582b8bbe 100644
--- a/app/views/repositories/_parse_records_modal.html.erb
+++ b/app/views/repositories/_parse_records_modal.html.erb
@@ -30,29 +30,31 @@
include_blank: t('teams.parse_sheet.do_not_include_column'),
hide_label: true) %>
- <% if th.length > Constants::NAME_TRUNCATION_LENGTH_DROPDOWN %>
-
<%= t('teams.parse_sheet.example_value') %>
+<%= t('teams.parse_sheet.example_value') %>
+ <%= td %><%= t('teams.parse_sheet.example_value') %>
+<%= t('teams.parse_sheet.example_value') %>
+ <%= td %>