importo 2.0.5 → 3.0.10
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.
- checksums.yaml +4 -4
- data/README.md +22 -5
- data/Rakefile +16 -17
- data/app/controllers/concerns/maintenance_standards.rb +1 -1
- data/app/controllers/importo/imports_controller.rb +15 -12
- data/app/helpers/importo/application_helper.rb +11 -11
- data/app/importers/concerns/exportable.rb +31 -24
- data/app/importers/concerns/importable.rb +144 -62
- data/app/importers/concerns/importer_dsl.rb +6 -14
- data/app/importers/concerns/original.rb +23 -23
- data/app/importers/concerns/result_feedback.rb +62 -44
- data/app/importers/concerns/revertable.rb +11 -12
- data/app/importers/importo/base_importer.rb +16 -4
- data/app/importers/importo/import_job_callback.rb +29 -0
- data/app/jobs/importo/import_job.rb +40 -0
- data/app/mailers/importo/application_mailer.rb +2 -2
- data/app/models/importo/import.rb +35 -8
- data/app/models/importo/result.rb +5 -0
- data/app/services/importo/import_service.rb +1 -3
- data/app/services/importo/revert_service.rb +1 -1
- data/app/tables/importo/imports_table.rb +13 -17
- data/app/tables/importo/mensa_imports_table.rb +35 -0
- data/app/views/importo/imports/index.html.slim +6 -2
- data/app/views/importo/imports/new.html.slim +30 -20
- data/config/locales/en.yml +21 -9
- data/config/locales/nl.yml +10 -4
- data/config/routes.rb +4 -4
- data/db/migrate/20180409151031_create_importo_import.rb +9 -9
- data/db/migrate/20180628175535_add_locale_importo_import.rb +1 -1
- data/db/migrate/20230510051447_remove_result_from_imports.rb +5 -0
- data/db/migrate/20230510083043_create_importo_results.rb +11 -0
- data/lib/generators/importo/importer_generator.rb +1 -1
- data/lib/generators/importo/install_generator.rb +7 -8
- data/lib/generators/importo/templates/importo.rb +11 -0
- data/lib/generators/satis/install_generator.rb +22 -0
- data/lib/generators/satis/tailwind_config_generator.rb +24 -0
- data/lib/generators/satis/templates/config/initializers/satis.rb +13 -0
- data/lib/importo/acts_as_import_owner.rb +1 -1
- data/lib/importo/configuration.rb +52 -49
- data/lib/importo/engine.rb +11 -9
- data/lib/importo/import_column.rb +18 -6
- data/lib/importo/test_helpers.rb +19 -0
- data/lib/importo/version.rb +1 -1
- data/lib/importo.rb +12 -17
- metadata +75 -24
- data/app/services/importo/callback_service.rb +0 -14
- data/lib/generators/templates/importo.rb +0 -21
- /data/lib/generators/{templates → importo/templates}/README +0 -0
- /data/lib/generators/{templates → importo/templates}/application_importer.rb +0 -0
- /data/lib/generators/{templates → importo/templates}/importer.rb +0 -0
@@ -1,24 +1,34 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
=
|
1
|
+
.grid.grid-cols-1.gap-4.sm:grid-cols-3.mt-4
|
2
|
+
.col-span-3.sm:col-span-3
|
3
|
+
= sts.form_for(@import) do |f|
|
4
|
+
= f.input :kind, as: :hidden
|
5
|
+
= sts.card :"importo_imports #{@import.kind}", title: t('.title'), icon: 'fad fa-file-spreadsheet' do |card|
|
6
|
+
- card.with_action
|
7
|
+
= f.submit
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
.grid.grid-cols-12.gap-4
|
10
|
+
.col-span-12
|
11
|
+
.prose
|
12
|
+
p= t('.explanation_html', name: @import.importer.class.friendly_name, sample_path: sample_import_path(kind: @import.kind))
|
13
|
+
- if @import.allow_export?
|
14
|
+
p= t('.export_html', export_path: export_path(kind: @import.kind))
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
16
|
+
.col-span-12
|
17
|
+
- @import.importer.overridable_columns.each do |column|
|
18
|
+
= f.fields_for :column_overrides do |fff|
|
19
|
+
- if column.collection
|
20
|
+
= fff.input column.attribute, as: :select, label: column.name, collection: column.collection, include_blank: true, required: false
|
21
|
+
- else
|
22
|
+
= fff.input column.attribute, label: column.name, required: false
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
+
.col-span-12
|
25
|
+
= f.input :original, as: :file
|
26
|
+
|
27
|
+
.grid.grid-cols-1.gap-4.sm:grid-cols-3.mt-4
|
28
|
+
.col-span-3.sm:col-span-3
|
29
|
+
= sts.card :importo_imports, title: "#{@import.kind.humanize} imports", icon: 'fad fa-file-import', content_padding: false do |card|
|
30
|
+
- if defined? Mensa
|
31
|
+
= sts.mensa(:importo_mensa_imports, parameters: { kind: @import.kind })
|
32
|
+
- else
|
33
|
+
= card.with_table(:importo_imports, parameters: { kind: @import.kind }, custom_views: false)
|
24
34
|
|
data/config/locales/en.yml
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
en:
|
2
2
|
helpers:
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
submit:
|
4
|
+
importo/import:
|
5
|
+
create: "Import"
|
6
6
|
importo:
|
7
7
|
sheet:
|
8
8
|
results:
|
@@ -10,24 +10,36 @@ en:
|
|
10
10
|
explanation:
|
11
11
|
name: Explanation
|
12
12
|
column: Column
|
13
|
-
|
13
|
+
value: Value
|
14
|
+
explanation: Purpose
|
15
|
+
example: Example
|
14
16
|
imports:
|
15
17
|
index:
|
16
18
|
title: Import results
|
19
|
+
card:
|
20
|
+
importo_imports:
|
21
|
+
title: Import results
|
22
|
+
tab:
|
23
|
+
Imports: Imports
|
17
24
|
new:
|
18
|
-
submit:
|
25
|
+
submit: "Import"
|
19
26
|
title: Import
|
20
27
|
explanation_html: A CSV or Excel file can be used to import records. The first row should be the column names.<br>If an <b>id</b> is supplied it will update the matching record instead of creating a new one.<br>Download a <a href='%{sample_path}' target='_blank'>sample template</a> with all supported column names and their explanation.
|
21
28
|
export_html: You can download the currently stored records.<br>Download the <a href='%{export_path}' target='_blank'>current data</a> with all supported columns
|
22
|
-
error_explanation:
|
29
|
+
error_explanation: "The following problems prohibited this import from completing:"
|
23
30
|
import: Import %{kind}
|
24
31
|
import_button: Import
|
32
|
+
card:
|
33
|
+
importo_imports:
|
34
|
+
tab:
|
35
|
+
importo_imports: Imports
|
25
36
|
create:
|
26
37
|
flash:
|
27
38
|
no_file: Import failed, please upload a file.
|
28
|
-
error: Import failed, there were problems.
|
29
|
-
success:
|
39
|
+
error: Import failed, there were problems %{error}.
|
40
|
+
success: "Import scheduled with id %{id}, you will get an email with the results."
|
30
41
|
errors:
|
31
|
-
|
42
|
+
parse_error: "We encountered a parse error: %{error}"
|
43
|
+
structure_invalid: "The structure is invalid, these are the invalid headers: %{invalid_headers}"
|
32
44
|
importers:
|
33
45
|
result_message: "Successfully imported %{nr} of %{of} rows"
|
data/config/locales/nl.yml
CHANGED
@@ -6,23 +6,29 @@ nl:
|
|
6
6
|
explanation:
|
7
7
|
name: Uitleg
|
8
8
|
column: Kolom
|
9
|
-
|
9
|
+
value: Waarde
|
10
|
+
explanation: Doeleinde
|
11
|
+
example: Voorbeeld
|
10
12
|
imports:
|
11
13
|
index:
|
12
14
|
title: Import resultaten
|
15
|
+
card:
|
16
|
+
importo_imports:
|
17
|
+
title: Imports
|
13
18
|
new:
|
14
19
|
import:
|
15
20
|
title: Importeer
|
16
21
|
explanation_html: Een CSV of Excel bestand kan gebruikt worden om records te importeren. De eerste rij moet de kolom namen bevatten.<br>Als een <b>id</b> is ingevuld, zal het bestaande record worden geupdate in plaats van een nieuwe aan te maken.<br>Download een <a href='%{sample_path}' target='_blank'>voorbeeld file</a> met alle ondersteunde kolomnamen en de bijbehorende uitleg.
|
17
|
-
error_explanation:
|
22
|
+
error_explanation: "De import is mislukt door de volgende problemen:"
|
18
23
|
import: Import %{kind}
|
19
24
|
import_button: Importeer
|
20
25
|
create:
|
21
26
|
flash:
|
22
27
|
no_file: Import mislukt, upload een bestand.
|
23
28
|
error: Import mislukt, er waren problemen, voor details zie hieronder.
|
24
|
-
success:
|
29
|
+
success: "Import geplanned met id %{id}, je krijgt een email met de resultaten."
|
25
30
|
errors:
|
26
|
-
|
31
|
+
parse_error: "We ondervonden een parse error: %{error}"
|
32
|
+
structure_invalid: "The structuur is ongeldig, dit zijn de ongeldige headers: %{invalid_headers}"
|
27
33
|
importers:
|
28
34
|
result_message: "%{nr} van %{of} rijen succesvol geimporteerd"
|
data/config/routes.rb
CHANGED
@@ -6,8 +6,8 @@ Importo::Engine.routes.draw do
|
|
6
6
|
post :undo
|
7
7
|
end
|
8
8
|
end
|
9
|
-
get
|
10
|
-
get
|
11
|
-
get
|
12
|
-
root to:
|
9
|
+
get ":kind/new", to: "imports#new", as: :new_import
|
10
|
+
get ":kind/sample", to: "imports#sample", as: :sample_import
|
11
|
+
get ":kind/export", to: "imports#export", as: :export
|
12
|
+
root to: "imports#index"
|
13
13
|
end
|
@@ -1,19 +1,19 @@
|
|
1
1
|
class CreateImportoImport < ActiveRecord::Migration[5.1]
|
2
2
|
def change
|
3
|
-
enable_extension
|
4
|
-
enable_extension
|
3
|
+
enable_extension "uuid-ossp"
|
4
|
+
enable_extension "pgcrypto"
|
5
5
|
|
6
6
|
return if table_exists?(:importo_imports)
|
7
7
|
|
8
8
|
create_table :importo_imports, id: :uuid do |t|
|
9
|
-
t.string
|
10
|
-
t.uuid
|
9
|
+
t.string :importo_ownable_type, null: false
|
10
|
+
t.uuid :importo_ownable_id, null: false
|
11
11
|
|
12
|
-
t.string
|
13
|
-
t.string
|
14
|
-
t.string
|
15
|
-
t.string
|
16
|
-
t.jsonb
|
12
|
+
t.string :kind
|
13
|
+
t.string :state
|
14
|
+
t.string :file_name
|
15
|
+
t.string :result_message
|
16
|
+
t.jsonb :results
|
17
17
|
|
18
18
|
t.timestamps
|
19
19
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class CreateImportoResults < ActiveRecord::Migration[7.0]
|
2
|
+
def change
|
3
|
+
create_table :importo_results, id: :uuid do |t|
|
4
|
+
t.integer :row_index
|
5
|
+
t.references :import, type: :uuid, null: false, foreign_key: {to_table: :importo_imports}
|
6
|
+
t.jsonb :details, default: {}
|
7
|
+
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Importo
|
2
2
|
class ImporterGenerator < Rails::Generators::NamedBase
|
3
|
-
source_root File.expand_path(
|
3
|
+
source_root File.expand_path("templates", __dir__)
|
4
4
|
|
5
5
|
def copy_initializer_file
|
6
6
|
template "application_importer.rb", "app/importers/application_importer.rb"
|
@@ -1,26 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "rails/generators/base"
|
4
4
|
|
5
5
|
module Importo
|
6
6
|
module Generators
|
7
|
-
|
8
7
|
class InstallGenerator < Rails::Generators::Base
|
9
|
-
source_root File.expand_path(
|
8
|
+
source_root File.expand_path("../templates", __dir__)
|
10
9
|
|
11
|
-
desc
|
10
|
+
desc "Creates a Importo initializer and copy locale files to your application."
|
12
11
|
|
13
12
|
def copy_initializer
|
14
|
-
template
|
13
|
+
template "importo.rb", "config/initializers/importo.rb"
|
15
14
|
end
|
16
15
|
|
17
16
|
def copy_locale
|
18
|
-
copy_file
|
19
|
-
copy_file
|
17
|
+
copy_file "../../../config/locales/en.yml", "config/locales/importo.en.yml"
|
18
|
+
copy_file "../../../config/locales/nl.yml", "config/locales/importo.nl.yml"
|
20
19
|
end
|
21
20
|
|
22
21
|
def show_readme
|
23
|
-
readme
|
22
|
+
readme "README" if behavior == :invoke
|
24
23
|
end
|
25
24
|
end
|
26
25
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Importo.setup do |config|
|
4
|
+
config.base_controller = "::ApplicationController"
|
5
|
+
config.admin_authentication_module = "Authenticated"
|
6
|
+
|
7
|
+
# Current import owner
|
8
|
+
config.current_import_owner = -> { Current.user }
|
9
|
+
|
10
|
+
config.queue_name = :import
|
11
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Satis
|
2
|
+
class InstallGenerator < Rails::Generators::Base
|
3
|
+
source_root File.expand_path("../templates", __FILE__)
|
4
|
+
|
5
|
+
def create_initializer_file
|
6
|
+
template "config/initializers/satis.rb"
|
7
|
+
end
|
8
|
+
|
9
|
+
def add_route
|
10
|
+
return if Rails.application.routes.routes.detect { |route| route.app.app == Satis::Engine }
|
11
|
+
route %(mount Satis::Engine => "/satis")
|
12
|
+
end
|
13
|
+
|
14
|
+
def copy_migrations
|
15
|
+
rake "satis:install:migrations"
|
16
|
+
end
|
17
|
+
|
18
|
+
def tailwindcss_config
|
19
|
+
rake "satis:tailwindcss:config"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "rails/generators/base"
|
2
|
+
|
3
|
+
module Satis
|
4
|
+
module Generators
|
5
|
+
class TailwindConfigGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path("../templates", __dir__)
|
7
|
+
desc "Configures tailwind.config.js and application.tailwindcss.css"
|
8
|
+
|
9
|
+
def add_content_to_tailwind_config
|
10
|
+
inject_into_file "config/tailwind.config.js", before: "],\n theme: {" do
|
11
|
+
" // Satis content\n" +
|
12
|
+
%w[/app/views/**/* /app/helpers/**/* /app/controllers/**/* /app/components/**/* /app/javascript/**/*.js /app/assets/**/*.css].map { |path| " \"#{Satis::Engine.root}#{path}\"" }.join(",\n") +
|
13
|
+
",\n "
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_content_application_tailwind_css
|
18
|
+
inject_into_file "app/assets/stylesheets/application.tailwind.css", before: "@tailwind base;" do
|
19
|
+
"@import '#{Satis::Engine.root}/app/assets/stylesheets/satis/application.css';\n"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Satis.setup do |config|
|
4
|
+
config.submit_on_enter = false
|
5
|
+
|
6
|
+
config.logger = Rails.logger
|
7
|
+
config.confirm_before_leave = false
|
8
|
+
config.current_user = -> { Current.user }
|
9
|
+
|
10
|
+
config.default_help_text = lambda do |template, object, key, additional_scope|
|
11
|
+
I18n.t((["help"] + [key.to_s]).join("."), default: nil)
|
12
|
+
end
|
13
|
+
end
|
@@ -1,68 +1,71 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Importo
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
attr_writer :logger
|
12
|
-
attr_writer :current_import_owner
|
13
|
-
attr_writer :import_callbacks
|
14
|
-
attr_writer :admin_visible_imports
|
15
|
-
attr_writer :admin_can_destroy
|
16
|
-
attr_writer :admin_extra_links
|
17
|
-
|
18
|
-
def initialize
|
19
|
-
@logger = Logger.new(STDOUT)
|
20
|
-
@logger.level = Logger::INFO
|
21
|
-
@base_controller = '::ApplicationController'
|
22
|
-
@base_service = '::ApplicationService'
|
23
|
-
@base_service_context = '::ApplicationContext'
|
24
|
-
@current_import_owner = -> {}
|
25
|
-
@import_callbacks = {
|
26
|
-
importing: lambda do |_import|
|
27
|
-
end,
|
28
|
-
completed: lambda do |_import|
|
29
|
-
end,
|
30
|
-
failed: lambda do |_import|
|
31
|
-
end
|
32
|
-
}
|
33
|
-
@queue_name = :import
|
4
|
+
module Options
|
5
|
+
module ClassMethods
|
6
|
+
def option(name, default: nil)
|
7
|
+
attr_accessor(name)
|
8
|
+
schema[name] = default
|
9
|
+
end
|
34
10
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
# Extra links relevant for this import: { link_name: { icon: 'far fa-..', url: '...' } }
|
39
|
-
@admin_extra_links = ->(_import) { }
|
11
|
+
def schema
|
12
|
+
@schema ||= {}
|
13
|
+
end
|
40
14
|
end
|
41
15
|
|
42
|
-
|
43
|
-
|
44
|
-
|
16
|
+
def set_defaults!
|
17
|
+
self.class.schema.each do |name, default|
|
18
|
+
instance_variable_set(:"@#{name}", default)
|
19
|
+
end
|
45
20
|
end
|
46
21
|
|
47
|
-
def
|
48
|
-
|
49
|
-
instance_exec(&@current_import_owner)
|
22
|
+
def self.included(cls)
|
23
|
+
cls.extend(ClassMethods)
|
50
24
|
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Configuration
|
28
|
+
include Options
|
29
|
+
|
30
|
+
option :logger, default: Rails.logger
|
31
|
+
option :admin_authentication_module
|
32
|
+
option :base_controller, default: "::ApplicationController"
|
33
|
+
option :base_service, default: "::ApplicationService"
|
34
|
+
option :base_service_context, default: "::ApplicationContext"
|
35
|
+
option :current_import_owner, default: lambda {}
|
36
|
+
option :queue_name, default: :import
|
37
|
+
|
38
|
+
option :admin_visible_imports, default: lambda { Importo::Import.where(importo_ownable: Importo.config.current_import_owner) }
|
39
|
+
option(:admin_can_destroy,
|
40
|
+
default: lambda do |import|
|
41
|
+
false
|
42
|
+
end)
|
43
|
+
|
44
|
+
# Extra links relevant for this import: { link_name: { icon: 'far fa-..', url: '...' } }
|
45
|
+
option(:admin_extra_links,
|
46
|
+
default: lambda do |import|
|
47
|
+
[]
|
48
|
+
end)
|
51
49
|
|
52
|
-
def
|
53
|
-
|
50
|
+
def initialize
|
51
|
+
set_defaults!
|
54
52
|
end
|
53
|
+
end
|
54
|
+
|
55
|
+
module Configurable
|
56
|
+
attr_writer :config
|
55
57
|
|
56
|
-
def
|
57
|
-
|
58
|
+
def config
|
59
|
+
@config ||= Configuration.new
|
58
60
|
end
|
59
61
|
|
60
|
-
def
|
61
|
-
|
62
|
+
def configure
|
63
|
+
yield(config)
|
62
64
|
end
|
65
|
+
alias_method :setup, :configure
|
63
66
|
|
64
|
-
def
|
65
|
-
|
67
|
+
def reset_config!
|
68
|
+
@config = Configuration.new
|
66
69
|
end
|
67
70
|
end
|
68
71
|
end
|
data/lib/importo/engine.rb
CHANGED
@@ -1,23 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "axlsx"
|
4
|
+
require "roo"
|
5
|
+
require "roo-xls"
|
6
|
+
require "slim"
|
7
|
+
require "state_machines-activerecord"
|
8
|
+
require "signum"
|
9
|
+
require "turbo-rails"
|
10
|
+
require "view_component"
|
11
|
+
require "with_advisory_lock"
|
12
|
+
|
3
13
|
module Importo
|
4
14
|
class Engine < ::Rails::Engine
|
5
15
|
isolate_namespace Importo
|
6
16
|
|
7
|
-
initializer
|
17
|
+
initializer "importo.active_storage.attached" do
|
8
18
|
config.after_initialize do
|
9
19
|
ActiveSupport.on_load(:active_record) do
|
10
20
|
Importo::Import.include(ImportHelpers)
|
11
21
|
end
|
12
22
|
end
|
13
23
|
end
|
14
|
-
|
15
|
-
initializer 'importo.append_migrations' do |app|
|
16
|
-
unless app.root.to_s.match?(root.to_s)
|
17
|
-
config.paths['db/migrate'].expanded.each do |expanded_path|
|
18
|
-
app.config.paths['db/migrate'] << expanded_path
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
24
|
end
|
23
25
|
end
|
@@ -3,12 +3,12 @@
|
|
3
3
|
module Importo
|
4
4
|
class ImportColumn
|
5
5
|
attr_accessor :proc, :options
|
6
|
-
attr_writer :name, :hint, :explanation
|
6
|
+
attr_writer :name, :hint, :explanation, :value, :example
|
7
7
|
|
8
|
-
def initialize(name
|
8
|
+
def initialize(name: nil, **options, &block)
|
9
9
|
@name = name
|
10
|
-
@hint = hint
|
11
|
-
@explanation = explanation
|
10
|
+
@hint = options[:hint]
|
11
|
+
@explanation = options[:explanation]
|
12
12
|
@options = options || {}
|
13
13
|
@proc = block
|
14
14
|
end
|
@@ -33,11 +33,19 @@ module Importo
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def hint
|
36
|
-
I18n.t(".hint.#{options[:attribute]}", scope: [:importers, options[:scope]], default:
|
36
|
+
I18n.t(".hint.#{options[:attribute]}", scope: [:importers, options[:scope]], default: "") if options[:attribute]
|
37
37
|
end
|
38
38
|
|
39
39
|
def explanation
|
40
|
-
I18n.t(".explanation.#{options[:attribute]}", scope: [:importers, options[:scope]], default:
|
40
|
+
I18n.t(".explanation.#{options[:attribute]}", scope: [:importers, options[:scope]], default: "") if options[:attribute]
|
41
|
+
end
|
42
|
+
|
43
|
+
def value
|
44
|
+
I18n.t(".value.#{options[:attribute]}", scope: [:importers, options[:scope]], default: "") if options[:attribute]
|
45
|
+
end
|
46
|
+
|
47
|
+
def example
|
48
|
+
I18n.t(".example.#{options[:attribute]}", scope: [:importers, options[:scope]], default: "") if options[:attribute]
|
41
49
|
end
|
42
50
|
|
43
51
|
##
|
@@ -51,5 +59,9 @@ module Importo
|
|
51
59
|
def collection
|
52
60
|
options[:collection]
|
53
61
|
end
|
62
|
+
|
63
|
+
def delay
|
64
|
+
options[:delay]
|
65
|
+
end
|
54
66
|
end
|
55
67
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "axlsx"
|
4
|
+
|
5
|
+
module Importo
|
6
|
+
module TestHelpers
|
7
|
+
def simple_sheet(an_array, sheet_name: "Import")
|
8
|
+
xls = Axlsx::Package.new
|
9
|
+
workbook = xls.workbook
|
10
|
+
sheet = workbook.add_worksheet(name: sheet_name)
|
11
|
+
|
12
|
+
an_array.each do |a|
|
13
|
+
sheet.add_row a
|
14
|
+
end
|
15
|
+
|
16
|
+
xls.to_stream
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/importo/version.rb
CHANGED
data/lib/importo.rb
CHANGED
@@ -1,29 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
# require 'active_storage/downloading'
|
9
|
-
|
10
|
-
require_relative 'importo/engine'
|
11
|
-
require_relative 'importo/acts_as_import_owner'
|
12
|
-
require_relative 'importo/import_column'
|
13
|
-
require_relative 'importo/import_helpers'
|
14
|
-
require_relative 'importo/configuration'
|
3
|
+
require_relative "importo/engine"
|
4
|
+
require_relative "importo/acts_as_import_owner"
|
5
|
+
require_relative "importo/import_column"
|
6
|
+
require_relative "importo/import_helpers"
|
7
|
+
require_relative "importo/configuration"
|
15
8
|
|
16
9
|
module Importo
|
10
|
+
extend Configurable
|
11
|
+
|
17
12
|
class Error < StandardError; end
|
18
13
|
|
19
14
|
class DuplicateRowError < Error; end
|
20
15
|
|
21
|
-
class
|
22
|
-
attr_reader :
|
16
|
+
class RetryError < StandardError
|
17
|
+
attr_reader :delay
|
23
18
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
19
|
+
def initialize(msg, delay)
|
20
|
+
super(msg)
|
21
|
+
@delay = delay
|
27
22
|
end
|
28
23
|
end
|
29
24
|
end
|