mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-09-20 23:16:15 +08:00
split the import service
This commit is contained in:
parent
2d3b5f4308
commit
70fa681519
|
@ -0,0 +1,53 @@
|
|||
(function(global) {
|
||||
'use strict';
|
||||
|
||||
global.repositoryRecordsImporter = function() {
|
||||
var previousIndex, disabledOptions, loadingSamples;
|
||||
loadingSamples = false;
|
||||
$('select').focus(function() {
|
||||
previousIndex = $(this)[0].selectedIndex;
|
||||
}).change(function() {
|
||||
var currSelect = $(this);
|
||||
var currIndex = $(currSelect)[0].selectedIndex;
|
||||
|
||||
$('select').each(function() {
|
||||
var el = $(this);
|
||||
if (currSelect !== el && currIndex > 0) {
|
||||
el.children().eq(currIndex).attr('disabled', 'disabled');
|
||||
}
|
||||
|
||||
el.children().eq(previousIndex).removeAttr('disabled');
|
||||
});
|
||||
|
||||
previousIndex = currIndex;
|
||||
});
|
||||
|
||||
// Create import samples ajax
|
||||
$('form#form-import').submit(function(e) {
|
||||
// Check if we already uploading samples
|
||||
if (loadingSamples) {
|
||||
return false;
|
||||
}
|
||||
disabledOptions = $("option[disabled='disabled']");
|
||||
disabledOptions.removeAttr('disabled');
|
||||
loadingSamples = true;
|
||||
animateSpinner();
|
||||
}).on('ajax:success', function(ev, data, status) {
|
||||
// Simply reload page to show flash and updated samples list
|
||||
loadingSamples = false;
|
||||
location.reload();
|
||||
}).on('ajax:error', function(ev, data, status) {
|
||||
loadingSamples = false;
|
||||
if (_.isUndefined(data.responseJSON.html)) {
|
||||
// Simply reload page to show flash
|
||||
location.reload();
|
||||
} else {
|
||||
// Re-disable options
|
||||
disabledOptions.attr('disabled', 'disabled');
|
||||
|
||||
// Populate the errors container
|
||||
$('#import-errors-container').html(data.responseJSON.html);
|
||||
}
|
||||
});
|
||||
}
|
||||
})(window);
|
|
@ -1,6 +1,36 @@
|
|||
//= require repositories/import/records_importer.js
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function showNewRepository() {
|
||||
$('#create-repo-modal').on('ajax:success', function(data) {
|
||||
var location = data.url;
|
||||
window.location.replace(location);
|
||||
});
|
||||
}
|
||||
|
||||
function initCreateRepository() {
|
||||
$('.create-repository').off().on('click', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
$.ajax({
|
||||
url: $(this).attr('href'),
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
$(data.html).appendTo('body').promise().done(function() {
|
||||
$('#create-repo-modal').modal('show');
|
||||
});
|
||||
},
|
||||
error: function() {
|
||||
location.reload();
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function loadRepositoryTab() {
|
||||
var param, pane;
|
||||
$('#repository-tabs a').on("click", function(e) {
|
||||
|
@ -8,7 +38,6 @@
|
|||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
pane = $(this);
|
||||
|
||||
$.ajax({
|
||||
url: pane.attr('data-url'),
|
||||
type: 'GET',
|
||||
|
@ -16,7 +45,9 @@
|
|||
success: function(data) {
|
||||
var tabBody = $(pane.context.hash).find('.tab-content-body');
|
||||
tabBody.html(data.html);
|
||||
pane.tab('show');
|
||||
pane.tab('show').promise().done(function() {
|
||||
initImportRecordsModal();
|
||||
});
|
||||
},
|
||||
error: function (error) {
|
||||
// TODO
|
||||
|
@ -40,20 +71,32 @@
|
|||
})
|
||||
}
|
||||
|
||||
function showParsedRecords() {
|
||||
$('#form-records-file').bind('ajax:success', function(evt, data, status, xhr) {
|
||||
debugger;
|
||||
function initImportRecordsModal() {
|
||||
$('#importRecordsButton').off().on('click', function() {
|
||||
$('#modal-import-records').modal('show');
|
||||
initParseRecordsModal();
|
||||
});
|
||||
}
|
||||
|
||||
function initParseRecordsModal() {
|
||||
$('#form-records-file').on('ajax:success', function(ev, data) {
|
||||
$('#modal-import-records').modal('hide');
|
||||
$(data.html).appendTo('body').promise().done(function() {
|
||||
$('#parse-records_modal').modal('show');
|
||||
repositoryRecordsImporter();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$('.delete-repo-option').initializeModal('#delete-repo-modal');
|
||||
$('.rename-repo-option').initializeModal('#rename-repo-modal');
|
||||
$('.copy-repo-option').initializeModal('#copy-repo-modal');
|
||||
$('.create-repository').initializeModal('#create-repo-modal');
|
||||
// $('.create-repository').initializeModal('#create-repo-modal');
|
||||
|
||||
$(document).ready(function() {
|
||||
loadRepositoryTab();
|
||||
showParsedRecords();
|
||||
// showParsedRecords();
|
||||
initCreateRepository();
|
||||
});
|
||||
|
||||
})();
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
class RepositoriesController < ApplicationController
|
||||
before_action :load_vars, except: [:repository_table_index, :parse_sheet]
|
||||
before_action :load_vars,
|
||||
except: %i(repository_table_index parse_sheet import_records)
|
||||
before_action :check_team, only: %i(parse_sheet import_records)
|
||||
before_action :check_view_all_permissions, only: :index
|
||||
before_action :check_edit_and_destroy_permissions, only:
|
||||
%(destroy destroy_modal rename_modal update)
|
||||
before_action :check_copy_permissions, only:
|
||||
%(copy_modal copy)
|
||||
before_action :check_create_permissions, only:
|
||||
%(create_new_modal create)
|
||||
before_action :check_edit_and_destroy_permissions,
|
||||
only: %i(destroy destroy_modal rename_modal update)
|
||||
before_action :check_copy_permissions,
|
||||
only: %i(copy_modal copy)
|
||||
before_action :check_create_permissions,
|
||||
only: %i(create_new_modal create)
|
||||
|
||||
def index
|
||||
render('repositories/index')
|
||||
|
@ -186,25 +188,27 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def parse_sheet
|
||||
render_404 unless params[:team_id].to_i == current_team.id
|
||||
repository = current_team.repositories.find_by_id(params[:id])
|
||||
imported_file = ::ImportRepository.new(file: params[:file],
|
||||
parsed_file = ImportRepository::ParseRepository.new(
|
||||
file: params[:file],
|
||||
repository: repository,
|
||||
session: session)
|
||||
session: session
|
||||
)
|
||||
|
||||
respond_to do |format|
|
||||
unless params[:file]
|
||||
repository_response(t("teams.parse_sheet.errors.no_file_selected"))
|
||||
return
|
||||
end
|
||||
begin
|
||||
if imported_file.too_large?
|
||||
if parsed_file.too_large?
|
||||
repository_response(t('general.file.size_exceeded',
|
||||
file_size: Constants::FILE_MAX_SIZE_MB))
|
||||
else
|
||||
flash[:notice] = t('teams.parse_sheet.errors.empty_file')
|
||||
redirect_to back and return if imported_file.empty?
|
||||
@import_data = imported_file.data
|
||||
if imported_file.generated_temp_file?
|
||||
redirect_to back and return if parsed_file.empty?
|
||||
@import_data = parsed_file.data
|
||||
if parsed_file.generated_temp_file?
|
||||
format.json do
|
||||
render json: {
|
||||
html: render_to_string(
|
||||
|
@ -225,7 +229,16 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def import_repository
|
||||
def import_records
|
||||
# byebug
|
||||
import_records = ImportRepository::ImportRecords.new(
|
||||
temp_file: TempFile.find_by_id(params[:file_id]),
|
||||
repository: current_team.repositories.find_by_id(params[:id]),
|
||||
mappings: params[:mappings],
|
||||
session: session,
|
||||
user: current_user
|
||||
)
|
||||
import_records.import!
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -236,6 +249,10 @@ class RepositoriesController < ApplicationController
|
|||
@repositories = @team.repositories.order(created_at: :asc)
|
||||
end
|
||||
|
||||
def check_team
|
||||
render_404 unless params[:team_id].to_i == current_team.id
|
||||
end
|
||||
|
||||
def check_view_all_permissions
|
||||
render_403 unless can_view_team_repositories(@team)
|
||||
end
|
||||
|
|
|
@ -64,8 +64,113 @@ class Repository < ActiveRecord::Base
|
|||
new_repo
|
||||
end
|
||||
|
||||
# Imports records
|
||||
def import_records(sheet, mappings, user)
|
||||
errors = []
|
||||
custom_fields = []
|
||||
name_index = -1
|
||||
header = sheet.row(1)
|
||||
generate_new_columns(header)
|
||||
|
||||
mappings.each.with_index do |(k, v), i|
|
||||
if v == '-1'
|
||||
# Fill blank space, so our indices stay the same
|
||||
custom_fields << nil
|
||||
name_index = i
|
||||
else
|
||||
cf = repository_columns.find_by_name(header[i])
|
||||
|
||||
custom_fields << cf
|
||||
end
|
||||
end
|
||||
# byebug
|
||||
# Now we can iterate through sample data and save stuff into db
|
||||
(2..sheet.last_row).each do |i|
|
||||
byebug
|
||||
error = []
|
||||
total_nr += 1
|
||||
byebug
|
||||
record_row = RepositoryRow.new(name: sheet.row(i)[name_index],
|
||||
repository: self,
|
||||
created_by: user,
|
||||
last_modified_by: user)
|
||||
|
||||
|
||||
if record.save
|
||||
sheet.row(i).each.with_index do |value, index|
|
||||
# We need to have sample saved before messing with custom fields (they
|
||||
# need sample id)
|
||||
if custom_fields[index]
|
||||
# we're working with CustomField
|
||||
rep_column = RepositoryTextValue.new(
|
||||
data: value,
|
||||
created_by:
|
||||
last_modified_by:
|
||||
repository_cell_attributes: {
|
||||
repository_row: record,
|
||||
repository_column: column
|
||||
}
|
||||
)
|
||||
|
||||
if scf.save
|
||||
|
||||
error << scf.errors.messages
|
||||
end
|
||||
else
|
||||
# This custom_field does not exist
|
||||
error << {"#{mappings[index]}": "Does not exists"}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
#
|
||||
# params[:repository_cells].each do |key, value|
|
||||
# column = @repository.repository_columns.detect do |c|
|
||||
# c.id == key.to_i
|
||||
# end
|
||||
# cell_value = RepositoryTextValue.new(
|
||||
# data: value,
|
||||
# created_by: current_user,
|
||||
# last_modified_by: current_user,
|
||||
# repository_cell_attributes: {
|
||||
# repository_row: record,
|
||||
# repository_column: column
|
||||
# }
|
||||
# )
|
||||
# unless cell_value.save
|
||||
# errors[:repository_cells] << {
|
||||
# "#{cell.repository_column.id}": cell_value.errors.messages
|
||||
# }
|
||||
# raise ActiveRecord::RecordInvalid
|
||||
# end
|
||||
# record_annotation_notification(record, cell_value.repository_cell)
|
||||
# end
|
||||
if errors.count > 0
|
||||
return {
|
||||
status: :error,
|
||||
errors: errors,
|
||||
nr_of_added: nr_of_added,
|
||||
total_nr: total_nr
|
||||
}
|
||||
else
|
||||
return {
|
||||
status: :ok,
|
||||
nr_of_added: nr_of_added,
|
||||
total_nr: total_nr
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generate_new_columns(header)
|
||||
rep_columns_names = self.repository_columns.pluck(:name).push('Name')
|
||||
header.each do |cname|
|
||||
next if rep_columns_names.include? cname
|
||||
RepositoryColumn.create(repository: self, name: cname, data_type: 0)
|
||||
end
|
||||
end
|
||||
|
||||
def generate_file(filename, file_path)
|
||||
case File.extname(filename)
|
||||
when '.csv'
|
||||
|
|
|
@ -1,363 +0,0 @@
|
|||
class ImportRepository
|
||||
include ActionView::Helpers::TextHelper
|
||||
def initialize(options)
|
||||
@file = options.fetch(:file)
|
||||
@repository = options.fetch(:repository)
|
||||
@session = options.fetch(:session)
|
||||
@sheet = @repository.open_spreadsheet(@file)
|
||||
end
|
||||
|
||||
def data
|
||||
# Get data (it will trigger any errors as well)
|
||||
header = @sheet.row(1)
|
||||
rows = []
|
||||
rows << Hash[[header, @sheet.row(2)].transpose]
|
||||
# Fill in fields for dropdown
|
||||
available_fields = @repository.available_repository_fields.map do |name|
|
||||
truncate(name.last, length: Constants::NAME_TRUNCATION_LENGTH_DROPDOWN)
|
||||
end
|
||||
@temp_file = TempFile.new(session_id: @session.id, file: @file)
|
||||
Data.new(header, rows, available_fields, @repository, @temp_file)
|
||||
end
|
||||
|
||||
def too_large?
|
||||
@file.size > Constants::FILE_MAX_SIZE_MB.megabytes
|
||||
end
|
||||
|
||||
def empty?
|
||||
@sheet.last_row.between?(0, 1)
|
||||
end
|
||||
|
||||
def generated_temp_file?
|
||||
# Save file for next step (importing)
|
||||
@temp_file = TempFile.new(
|
||||
session_id: @session.id,
|
||||
file: @file
|
||||
)
|
||||
|
||||
if @temp_file.save
|
||||
@temp_file.destroy_obsolete
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
Data = Struct.new(
|
||||
:header, :rows, :available_fields, :repository, :temp_file
|
||||
)
|
||||
# def import_repository
|
||||
# session[:return_to] ||= request.referer
|
||||
#
|
||||
# respond_to do |format|
|
||||
# if params[:file_id]
|
||||
# @temp_file = TempFile.find_by_id(params[:file_id])
|
||||
#
|
||||
# if @temp_file
|
||||
# # Check if session_id is equal to prevent file stealing
|
||||
# if @temp_file.session_id == session.id
|
||||
# # Check if mappings exists or else we don't have anything to parse
|
||||
# if params[:mappings]
|
||||
# @sheet = Team.open_spreadsheet(@temp_file.file)
|
||||
#
|
||||
# # Check for duplicated values
|
||||
# h1 = params[:mappings].clone.delete_if { |k, v| v.empty? }
|
||||
# if h1.length == h1.invert.length
|
||||
#
|
||||
# # Check if there exist mapping for sample name (it's mandatory)
|
||||
# if params[:mappings].has_value?("-1")
|
||||
# result = @team.import_samples(@sheet, params[:mappings], current_user)
|
||||
# nr_of_added = result[:nr_of_added]
|
||||
# total_nr = result[:total_nr]
|
||||
#
|
||||
# if result[:status] == :ok
|
||||
# # If no errors are present, redirect back
|
||||
# # to samples table
|
||||
# flash[:success] = t(
|
||||
# "teams.import_samples.success_flash",
|
||||
# nr: nr_of_added,
|
||||
# samples: t(
|
||||
# "teams.import_samples.sample",
|
||||
# count: total_nr
|
||||
# )
|
||||
# )
|
||||
# @temp_file.destroy
|
||||
# format.html {
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# flash.keep(:success)
|
||||
# render json: { status: :ok }
|
||||
# }
|
||||
# else
|
||||
# # Otherwise, also redirect back,
|
||||
# # but display different message
|
||||
# flash[:alert] = t(
|
||||
# "teams.import_samples.partial_success_flash",
|
||||
# nr: nr_of_added,
|
||||
# samples: t(
|
||||
# "teams.import_samples.sample",
|
||||
# count: total_nr
|
||||
# )
|
||||
# )
|
||||
# @temp_file.destroy
|
||||
# format.html {
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# flash.keep(:alert)
|
||||
# render json: { status: :unprocessable_entity }
|
||||
# }
|
||||
# end
|
||||
# else
|
||||
# # This is currently the only AJAX error response
|
||||
# flash_alert = t(
|
||||
# "teams.import_samples.errors.no_sample_name")
|
||||
# format.html {
|
||||
# flash[:alert] = flash_alert
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# render json: {
|
||||
# html: render_to_string({
|
||||
# partial: "parse_error.html.erb",
|
||||
# locals: { error: flash_alert }
|
||||
# })
|
||||
# },
|
||||
# status: :unprocessable_entity
|
||||
# }
|
||||
# end
|
||||
# else
|
||||
# # This code should never execute unless user tampers with
|
||||
# # JS (selects same column in more than one dropdown)
|
||||
# flash_alert = t(
|
||||
# "teams.import_samples.errors.duplicated_values")
|
||||
# format.html {
|
||||
# flash[:alert] = flash_alert
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# render json: {
|
||||
# html: render_to_string({
|
||||
# partial: "parse_error.html.erb",
|
||||
# locals: { error: flash_alert }
|
||||
# })
|
||||
# },
|
||||
# status: :unprocessable_entity
|
||||
# }
|
||||
# end
|
||||
# else
|
||||
# @temp_file.destroy
|
||||
# flash[:alert] = t(
|
||||
# "teams.import_samples.errors.no_data_to_parse")
|
||||
# format.html {
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# flash.keep(:alert)
|
||||
# render json: { status: :unprocessable_entity }
|
||||
# }
|
||||
# end
|
||||
# else
|
||||
# @temp_file.destroy
|
||||
# flash[:alert] = t(
|
||||
# "teams.import_samples.errors.session_expired")
|
||||
# format.html {
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# flash.keep(:alert)
|
||||
# render json: { status: :unprocessable_entity }
|
||||
# }
|
||||
# end
|
||||
# else
|
||||
# # No temp file to begin with, so no need to destroy it
|
||||
# flash[:alert] = t(
|
||||
# "teams.import_samples.errors.temp_file_not_found")
|
||||
# format.html {
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# flash.keep(:alert)
|
||||
# render json: { status: :unprocessable_entity }
|
||||
# }
|
||||
# end
|
||||
# else
|
||||
# flash[:alert] = t(
|
||||
# "teams.import_samples.errors.temp_file_not_found")
|
||||
# format.html {
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# flash.keep(:alert)
|
||||
# render json: { status: :unprocessable_entity }
|
||||
# }
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# def parse_sheet
|
||||
# session[:return_to] ||= request.referer
|
||||
#
|
||||
# respond_to do |format|
|
||||
# if params[:file]
|
||||
# begin
|
||||
#
|
||||
# if params[:file].size > Constants::FILE_MAX_SIZE_MB.megabytes
|
||||
# error = t 'general.file.size_exceeded',
|
||||
# file_size: Constants::FILE_MAX_SIZE_MB
|
||||
#
|
||||
# format.html {
|
||||
# flash[:alert] = error
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# render json: {message: error},
|
||||
# status: :unprocessable_entity
|
||||
# }
|
||||
#
|
||||
# else
|
||||
# sheet = Team.open_spreadsheet(params[:file])
|
||||
#
|
||||
# # Check if we actually have any rows (last_row > 1)
|
||||
# if sheet.last_row.between?(0, 1)
|
||||
# flash[:notice] = t(
|
||||
# "teams.parse_sheet.errors.empty_file")
|
||||
# redirect_to session.delete(:return_to) and return
|
||||
# end
|
||||
#
|
||||
# # Get data (it will trigger any errors as well)
|
||||
# @header = sheet.row(1)
|
||||
# @rows = [];
|
||||
# @rows << Hash[[@header, sheet.row(2)].transpose]
|
||||
#
|
||||
# # Fill in fields for dropdown
|
||||
# @available_fields = @team.get_available_sample_fields
|
||||
# # Truncate long fields
|
||||
# @available_fields.update(@available_fields) do |_k, v|
|
||||
# v.truncate(Constants::NAME_TRUNCATION_LENGTH_DROPDOWN)
|
||||
# end
|
||||
#
|
||||
# # Save file for next step (importing)
|
||||
# @temp_file = TempFile.new(
|
||||
# session_id: session.id,
|
||||
# file: params[:file]
|
||||
# )
|
||||
#
|
||||
# if @temp_file.save
|
||||
# @temp_file.destroy_obsolete
|
||||
# # format.html
|
||||
# format.json {
|
||||
# render :json => {
|
||||
# :html => render_to_string({
|
||||
# :partial => "samples/parse_samples_modal.html.erb"
|
||||
# })
|
||||
# }
|
||||
# }
|
||||
# else
|
||||
# error = t("teams.parse_sheet.errors.temp_file_failure")
|
||||
# format.html {
|
||||
# flash[:alert] = error
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# render json: {message: error},
|
||||
# status: :unprocessable_entity
|
||||
# }
|
||||
# end
|
||||
# end
|
||||
# rescue ArgumentError, CSV::MalformedCSVError
|
||||
# error = t('teams.parse_sheet.errors.invalid_file',
|
||||
# encoding: ''.encoding)
|
||||
# format.html {
|
||||
# flash[:alert] = error
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# render json: {message: error},
|
||||
# status: :unprocessable_entity
|
||||
# }
|
||||
# rescue TypeError
|
||||
# error = t("teams.parse_sheet.errors.invalid_extension")
|
||||
# format.html {
|
||||
# flash[:alert] = error
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# render json: {message: error},
|
||||
# status: :unprocessable_entity
|
||||
# }
|
||||
# end
|
||||
# else
|
||||
# error = t("teams.parse_sheet.errors.no_file_selected")
|
||||
# format.html {
|
||||
# flash[:alert] = error
|
||||
# session[:return_to] ||= request.referer
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# render json: {message: error},
|
||||
# status: :unprocessable_entity
|
||||
# }
|
||||
# end
|
||||
# end
|
||||
# end format.json {
|
||||
# render json: {message: error},
|
||||
# status: :unprocessable_entity
|
||||
# }
|
||||
# rescue TypeError
|
||||
# error = t("teams.parse_sheet.errors.invalid_extension")
|
||||
# format.html {
|
||||
# flash[:alert] = error
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# render json: {message: error},
|
||||
# status: :unprocessable_entity
|
||||
# }
|
||||
# end
|
||||
# else
|
||||
# error = t("teams.parse_sheet.errors.no_file_selected")
|
||||
# format.html {
|
||||
# flash[:alert] = error
|
||||
# session[:return_to] ||= request.referer
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# render json: {message: error},
|
||||
# status: :unprocessable_entity
|
||||
# }
|
||||
# end
|
||||
# end
|
||||
# end format.json {
|
||||
# render json: {message: error},
|
||||
# status: :unprocessable_entity
|
||||
# }
|
||||
# rescue TypeError
|
||||
# error = t("teams.parse_sheet.errors.invalid_extension")
|
||||
# format.html {
|
||||
# flash[:alert] = error
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# render json: {message: error},
|
||||
# status: :unprocessable_entity
|
||||
# }
|
||||
# end
|
||||
# else
|
||||
# error = t("teams.parse_sheet.errors.no_file_selected")
|
||||
# format.html {
|
||||
# flash[:alert] = error
|
||||
# session[:return_to] ||= request.referer
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# render json: {message: error},
|
||||
# status: :unprocessable_entity
|
||||
# }
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
end
|
183
app/services/import_repository/import_records.rb
Normal file
183
app/services/import_repository/import_records.rb
Normal file
|
@ -0,0 +1,183 @@
|
|||
module ImportRepository
|
||||
class ImportRecords
|
||||
def initialize(options)
|
||||
@temp_file = options.fetch(:temp_file)
|
||||
@repository = options.fetch(:repository)
|
||||
@mappings = options.fetch(:mappings)
|
||||
@session = options.fetch(:session)
|
||||
@user = options.fetch(:user)
|
||||
end
|
||||
|
||||
def has_temp_file?
|
||||
@temp_file
|
||||
end
|
||||
|
||||
def session_valid?
|
||||
@temp_file.session_id == session.id
|
||||
end
|
||||
|
||||
def import!
|
||||
unless @mappings
|
||||
return { error: t('teams.import_samples.errors.no_data_to_parse') }
|
||||
end
|
||||
sheet = @repository.open_spreadsheet(@temp_file.file)
|
||||
# Check for duplicated values
|
||||
h1 = @mappings.clone.delete_if { |k, v| v.empty? }
|
||||
unless @mappings.has_value?('-1')
|
||||
return { error: t('teams.import_samples.errors.no_sample_name') }
|
||||
end
|
||||
result = @repository.import_records(sheet, @mappings, @user)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# def import_repository
|
||||
# session[:return_to] ||= request.referer
|
||||
#
|
||||
# respond_to do |format|
|
||||
# if params[:file_id]
|
||||
# @temp_file = TempFile.find_by_id(params[:file_id])
|
||||
#
|
||||
# if @temp_file
|
||||
# # Check if session_id is equal to prevent file stealing
|
||||
# if @temp_file.session_id == session.id
|
||||
# # Check if mappings exists or else we don't have anything to parse
|
||||
# if params[:mappings]
|
||||
# @sheet = Team.open_spreadsheet(@temp_file.file)
|
||||
#
|
||||
# # Check for duplicated values
|
||||
# h1 = params[:mappings].clone.delete_if { |k, v| v.empty? }
|
||||
# if h1.length == h1.invert.length
|
||||
#
|
||||
# # Check if there exist mapping for sample name (it's mandatory)
|
||||
# if params[:mappings].has_value?("-1")
|
||||
# result = @team.import_samples(@sheet, params[:mappings], current_user)
|
||||
# nr_of_added = result[:nr_of_added]
|
||||
# total_nr = result[:total_nr]
|
||||
#
|
||||
# if result[:status] == :ok
|
||||
# # If no errors are present, redirect back
|
||||
# # to samples table
|
||||
# flash[:success] = t(
|
||||
# "teams.import_samples.success_flash",
|
||||
# nr: nr_of_added,
|
||||
# samples: t(
|
||||
# "teams.import_samples.sample",
|
||||
# count: total_nr
|
||||
# )
|
||||
# )
|
||||
# @temp_file.destroy
|
||||
# format.html {
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# flash.keep(:success)
|
||||
# render json: { status: :ok }
|
||||
# }
|
||||
# else
|
||||
# # Otherwise, also redirect back,
|
||||
# # but display different message
|
||||
# flash[:alert] = t(
|
||||
# "teams.import_samples.partial_success_flash",
|
||||
# nr: nr_of_added,
|
||||
# samples: t(
|
||||
# "teams.import_samples.sample",
|
||||
# count: total_nr
|
||||
# )
|
||||
# )
|
||||
# @temp_file.destroy
|
||||
# format.html {
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# flash.keep(:alert)
|
||||
# render json: { status: :unprocessable_entity }
|
||||
# }
|
||||
# end
|
||||
# else
|
||||
# # This is currently the only AJAX error response
|
||||
# flash_alert = t(
|
||||
# "teams.import_samples.errors.no_sample_name")
|
||||
# format.html {
|
||||
# flash[:alert] = flash_alert
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# render json: {
|
||||
# html: render_to_string({
|
||||
# partial: "parse_error.html.erb",
|
||||
# locals: { error: flash_alert }
|
||||
# })
|
||||
# },
|
||||
# status: :unprocessable_entity
|
||||
# }
|
||||
# end
|
||||
# else
|
||||
# # This code should never execute unless user tampers with
|
||||
# # JS (selects same column in more than one dropdown)
|
||||
# flash_alert = t(
|
||||
# "teams.import_samples.errors.duplicated_values")
|
||||
# format.html {
|
||||
# flash[:alert] = flash_alert
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# render json: {
|
||||
# html: render_to_string({
|
||||
# partial: "parse_error.html.erb",
|
||||
# locals: { error: flash_alert }
|
||||
# })
|
||||
# },
|
||||
# status: :unprocessable_entity
|
||||
# }
|
||||
# end
|
||||
# else
|
||||
# @temp_file.destroy
|
||||
# flash[:alert] = t(
|
||||
# "teams.import_samples.errors.no_data_to_parse")
|
||||
# format.html {
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# flash.keep(:alert)
|
||||
# render json: { status: :unprocessable_entity }
|
||||
# }
|
||||
# end
|
||||
# else
|
||||
# @temp_file.destroy
|
||||
# flash[:alert] = t(
|
||||
# "teams.import_samples.errors.session_expired")
|
||||
# format.html {
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# flash.keep(:alert)
|
||||
# render json: { status: :unprocessable_entity }
|
||||
# }
|
||||
# end
|
||||
# else
|
||||
# # No temp file to begin with, so no need to destroy it
|
||||
# flash[:alert] = t(
|
||||
# "teams.import_samples.errors.temp_file_not_found")
|
||||
# format.html {
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# flash.keep(:alert)
|
||||
# render json: { status: :unprocessable_entity }
|
||||
# }
|
||||
# end
|
||||
# else
|
||||
# flash[:alert] = t(
|
||||
# "teams.import_samples.errors.temp_file_not_found")
|
||||
# format.html {
|
||||
# redirect_to session.delete(:return_to)
|
||||
# }
|
||||
# format.json {
|
||||
# flash.keep(:alert)
|
||||
# render json: { status: :unprocessable_entity }
|
||||
# }
|
||||
# end
|
||||
# end
|
||||
# end
|
53
app/services/import_repository/parse_repository.rb
Normal file
53
app/services/import_repository/parse_repository.rb
Normal file
|
@ -0,0 +1,53 @@
|
|||
module ImportRepository
|
||||
class ParseRepository
|
||||
include ActionView::Helpers::TextHelper
|
||||
def initialize(options)
|
||||
@file = options.fetch(:file)
|
||||
@repository = options.fetch(:repository)
|
||||
@session = options.fetch(:session)
|
||||
@sheet = @repository.open_spreadsheet(@file)
|
||||
end
|
||||
|
||||
def data
|
||||
# Get data (it will trigger any errors as well)
|
||||
header = @sheet.row(1)
|
||||
rows = []
|
||||
rows << Hash[[header, @sheet.row(2)].transpose]
|
||||
# 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,
|
||||
@repository.available_repository_fields,
|
||||
@repository,
|
||||
@temp_file)
|
||||
end
|
||||
|
||||
def too_large?
|
||||
@file.size > Constants::FILE_MAX_SIZE_MB.megabytes
|
||||
end
|
||||
|
||||
def empty?
|
||||
@sheet.last_row.between?(0, 1)
|
||||
end
|
||||
|
||||
def generated_temp_file?
|
||||
# Save file for next step (importing)
|
||||
@temp_file = TempFile.new(
|
||||
session_id: @session.id,
|
||||
file: @file
|
||||
)
|
||||
|
||||
if @temp_file.save
|
||||
@temp_file.destroy_obsolete
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
Data = Struct.new(
|
||||
:header, :rows, :available_fields, :repository, :temp_file
|
||||
)
|
||||
end
|
||||
end
|
|
@ -1,12 +1,17 @@
|
|||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal fade"
|
||||
id="parse-records_modal"
|
||||
aria-labelledby="parse-modal-title"
|
||||
role="dialog">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title"><%= t('samples.modal_import.title') %></h4>
|
||||
<h4 class="modal-title" id="parse-modal-title"><%= t('samples.modal_import.title') %></h4>
|
||||
</div>
|
||||
<%= bootstrap_form_tag(url: import_records_repository_path(@import_data.repository, format: :json),
|
||||
html: {'data-type' => 'json', id: 'form-import'},
|
||||
remote: true) do |f|%>
|
||||
<%= f.hidden_field :team_id, value: current_team.id %>
|
||||
<div class="modal-body">
|
||||
<h4><%= t("teams.parse_sheet.help_text") %></h4>
|
||||
<div style="overflow-x: scroll">
|
||||
|
@ -63,5 +68,6 @@
|
|||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= javascript_include_tag('samples/samples_importer') %>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
</button>
|
||||
<% end %>
|
||||
<% if can_import_repository_records(repository) %>
|
||||
<button type="button" class="btn btn-default" id="importRecordsButton" data-toggle="modal" data-target="#modal-import-records">
|
||||
<button type="button" class="btn btn-default" id="importRecordsButton">
|
||||
<span class="glyphicon glyphicon-cloud-upload"></span>
|
||||
<span class="hidden-xs"><%= t('repositories.import_records') %></span>
|
||||
</button>
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
<% if can_create_repository(current_team) %>
|
||||
href="<%= create_modal_team_repositories_path %>"
|
||||
class='create-repository'
|
||||
data-remote='true'
|
||||
<% end %>>
|
||||
<span class="glyphicon glyphicon-plus"></span>
|
||||
<span class="hidden-xs"> <%= t('repositories.index.add_new_repository_tab') %></span>
|
||||
|
|
Loading…
Reference in a new issue