bulkrax 1.0.0

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.
Files changed (133) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +205 -0
  3. data/README.md +202 -0
  4. data/Rakefile +42 -0
  5. data/app/assets/config/bulkrax_manifest.js +2 -0
  6. data/app/assets/javascripts/bulkrax/application.js +14 -0
  7. data/app/assets/javascripts/bulkrax/bulkrax.js +11 -0
  8. data/app/assets/javascripts/bulkrax/entries.js +15 -0
  9. data/app/assets/javascripts/bulkrax/exporters.js +60 -0
  10. data/app/assets/javascripts/bulkrax/importers.js.erb +166 -0
  11. data/app/assets/stylesheets/bulkrax/accordion.scss +40 -0
  12. data/app/assets/stylesheets/bulkrax/application.css +15 -0
  13. data/app/assets/stylesheets/bulkrax/coderay.scss +264 -0
  14. data/app/assets/stylesheets/bulkrax/import_export.scss +37 -0
  15. data/app/controllers/bulkrax/application_controller.rb +8 -0
  16. data/app/controllers/bulkrax/entries_controller.rb +44 -0
  17. data/app/controllers/bulkrax/exporters_controller.rb +125 -0
  18. data/app/controllers/bulkrax/importers_controller.rb +315 -0
  19. data/app/controllers/concerns/bulkrax/api.rb +29 -0
  20. data/app/factories/bulkrax/object_factory.rb +230 -0
  21. data/app/helpers/bulkrax/application_helper.rb +15 -0
  22. data/app/helpers/bulkrax/exporters_helper.rb +6 -0
  23. data/app/helpers/bulkrax/importers_helper.rb +13 -0
  24. data/app/helpers/bulkrax/validation_helper.rb +153 -0
  25. data/app/jobs/bulkrax/application_job.rb +6 -0
  26. data/app/jobs/bulkrax/child_relationships_job.rb +128 -0
  27. data/app/jobs/bulkrax/delete_work_job.rb +16 -0
  28. data/app/jobs/bulkrax/download_cloud_file_job.rb +18 -0
  29. data/app/jobs/bulkrax/export_work_job.rb +37 -0
  30. data/app/jobs/bulkrax/exporter_job.rb +14 -0
  31. data/app/jobs/bulkrax/import_work_collection_job.rb +41 -0
  32. data/app/jobs/bulkrax/import_work_job.rb +32 -0
  33. data/app/jobs/bulkrax/importer_job.rb +26 -0
  34. data/app/mailers/bulkrax/application_mailer.rb +8 -0
  35. data/app/matchers/bulkrax/application_matcher.rb +113 -0
  36. data/app/matchers/bulkrax/bagit_matcher.rb +6 -0
  37. data/app/matchers/bulkrax/csv_matcher.rb +6 -0
  38. data/app/matchers/bulkrax/oai_matcher.rb +6 -0
  39. data/app/models/bulkrax/application_record.rb +7 -0
  40. data/app/models/bulkrax/csv_collection_entry.rb +19 -0
  41. data/app/models/bulkrax/csv_entry.rb +163 -0
  42. data/app/models/bulkrax/entry.rb +104 -0
  43. data/app/models/bulkrax/exporter.rb +122 -0
  44. data/app/models/bulkrax/exporter_run.rb +7 -0
  45. data/app/models/bulkrax/import_failed.rb +13 -0
  46. data/app/models/bulkrax/importer.rb +155 -0
  47. data/app/models/bulkrax/importer_run.rb +8 -0
  48. data/app/models/bulkrax/oai_dc_entry.rb +6 -0
  49. data/app/models/bulkrax/oai_entry.rb +74 -0
  50. data/app/models/bulkrax/oai_qualified_dc_entry.rb +6 -0
  51. data/app/models/bulkrax/oai_set_entry.rb +19 -0
  52. data/app/models/bulkrax/rdf_collection_entry.rb +19 -0
  53. data/app/models/bulkrax/rdf_entry.rb +90 -0
  54. data/app/models/bulkrax/status.rb +25 -0
  55. data/app/models/bulkrax/xml_entry.rb +73 -0
  56. data/app/models/concerns/bulkrax/download_behavior.rb +61 -0
  57. data/app/models/concerns/bulkrax/errored_entries.rb +45 -0
  58. data/app/models/concerns/bulkrax/export_behavior.rb +58 -0
  59. data/app/models/concerns/bulkrax/file_factory.rb +140 -0
  60. data/app/models/concerns/bulkrax/has_local_processing.rb +7 -0
  61. data/app/models/concerns/bulkrax/has_matchers.rb +155 -0
  62. data/app/models/concerns/bulkrax/import_behavior.rb +90 -0
  63. data/app/models/concerns/bulkrax/importer_exporter_behavior.rb +34 -0
  64. data/app/models/concerns/bulkrax/status_info.rb +56 -0
  65. data/app/parsers/bulkrax/application_parser.rb +299 -0
  66. data/app/parsers/bulkrax/bagit_parser.rb +157 -0
  67. data/app/parsers/bulkrax/csv_parser.rb +266 -0
  68. data/app/parsers/bulkrax/oai_dc_parser.rb +130 -0
  69. data/app/parsers/bulkrax/oai_qualified_dc_parser.rb +9 -0
  70. data/app/parsers/bulkrax/xml_parser.rb +103 -0
  71. data/app/views/bulkrax/entries/_parsed_metadata.html.erb +19 -0
  72. data/app/views/bulkrax/entries/_raw_metadata.html.erb +19 -0
  73. data/app/views/bulkrax/entries/show.html.erb +63 -0
  74. data/app/views/bulkrax/exporters/_form.html.erb +120 -0
  75. data/app/views/bulkrax/exporters/edit.html.erb +23 -0
  76. data/app/views/bulkrax/exporters/index.html.erb +67 -0
  77. data/app/views/bulkrax/exporters/new.html.erb +23 -0
  78. data/app/views/bulkrax/exporters/show.html.erb +124 -0
  79. data/app/views/bulkrax/importers/_bagit_fields.html.erb +54 -0
  80. data/app/views/bulkrax/importers/_browse_everything.html.erb +12 -0
  81. data/app/views/bulkrax/importers/_csv_fields.html.erb +39 -0
  82. data/app/views/bulkrax/importers/_edit_form_buttons.html.erb +16 -0
  83. data/app/views/bulkrax/importers/_form.html.erb +35 -0
  84. data/app/views/bulkrax/importers/_oai_fields.html.erb +42 -0
  85. data/app/views/bulkrax/importers/_xml_fields.html.erb +60 -0
  86. data/app/views/bulkrax/importers/edit.html.erb +20 -0
  87. data/app/views/bulkrax/importers/index.html.erb +77 -0
  88. data/app/views/bulkrax/importers/new.html.erb +25 -0
  89. data/app/views/bulkrax/importers/show.html.erb +175 -0
  90. data/app/views/bulkrax/importers/upload_corrected_entries.html.erb +37 -0
  91. data/app/views/bulkrax/shared/_bulkrax_errors.html.erb +52 -0
  92. data/app/views/bulkrax/shared/_bulkrax_field_mapping.html.erb +39 -0
  93. data/app/views/hyrax/dashboard/sidebar/_bulkrax_sidebar_additions.html.erb +6 -0
  94. data/app/views/hyrax/dashboard/sidebar/_repository_content.html.erb +19 -0
  95. data/app/views/layouts/bulkrax/application.html.erb +14 -0
  96. data/config/locales/bulkrax.en.yml +36 -0
  97. data/config/routes.rb +18 -0
  98. data/db/migrate/20181011230201_create_bulkrax_importers.rb +18 -0
  99. data/db/migrate/20181011230228_create_bulkrax_importer_runs.rb +16 -0
  100. data/db/migrate/20190325183136_create_bulkrax_entries.rb +16 -0
  101. data/db/migrate/20190601221109_add_status_to_entry.rb +9 -0
  102. data/db/migrate/20190715161939_add_collections_to_importer_runs.rb +6 -0
  103. data/db/migrate/20190715162044_change_collection_ids_on_entries.rb +5 -0
  104. data/db/migrate/20190729124607_create_bulkrax_exporters.rb +19 -0
  105. data/db/migrate/20190729134158_create_bulkrax_exporter_runs.rb +14 -0
  106. data/db/migrate/20190731114016_change_importer_and_exporter_to_polymorphic.rb +12 -0
  107. data/db/migrate/20191203225129_add_total_collection_records_to_importer_runs.rb +5 -0
  108. data/db/migrate/20191204191623_add_children_to_importer_runs.rb +6 -0
  109. data/db/migrate/20191204223857_change_total_records_to_total_work_entries.rb +6 -0
  110. data/db/migrate/20191212155530_change_entry_last_error.rb +19 -0
  111. data/db/migrate/20200108194557_add_validate_only_to_bulkrax_importers.rb +5 -0
  112. data/db/migrate/20200301232856_add_status_to_importers.rb +9 -0
  113. data/db/migrate/20200312190638_remove_foreign_key_from_bulkrax_entries.rb +5 -0
  114. data/db/migrate/20200326235838_add_status_to_exporters.rb +7 -0
  115. data/db/migrate/20200601204556_add_invalid_record_to_importer_run.rb +5 -0
  116. data/db/migrate/20200818055819_create_bulkrax_statuses.rb +18 -0
  117. data/db/migrate/20200819054016_move_to_statuses.rb +30 -0
  118. data/db/migrate/20201106014204_add_date_filter_and_status_to_bulkrax_exporters.rb +7 -0
  119. data/db/migrate/20201117220007_add_workflow_status_to_bulkrax_exporter.rb +5 -0
  120. data/db/migrate/20210806044408_remove_unused_last_error.rb +7 -0
  121. data/db/migrate/20210806065737_increase_text_sizes.rb +12 -0
  122. data/lib/bulkrax.rb +161 -0
  123. data/lib/bulkrax/engine.rb +37 -0
  124. data/lib/bulkrax/version.rb +5 -0
  125. data/lib/generators/bulkrax/install_generator.rb +80 -0
  126. data/lib/generators/bulkrax/templates/README +3 -0
  127. data/lib/generators/bulkrax/templates/app/assets/images/bulkrax/removed.png +0 -0
  128. data/lib/generators/bulkrax/templates/app/models/concerns/bulkrax/has_local_processing.rb +8 -0
  129. data/lib/generators/bulkrax/templates/bin/importer +140 -0
  130. data/lib/generators/bulkrax/templates/config/bulkrax_api.yml +84 -0
  131. data/lib/generators/bulkrax/templates/config/initializers/bulkrax.rb +72 -0
  132. data/lib/tasks/bulkrax_tasks.rake +6 -0
  133. metadata +388 -0
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bulkrax
4
+ class BagitMatcher < ApplicationMatcher
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bulkrax
4
+ class CsvMatcher < ApplicationMatcher
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bulkrax
4
+ class OaiMatcher < ApplicationMatcher
5
+ end
6
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bulkrax
4
+ class ApplicationRecord < ActiveRecord::Base
5
+ self.abstract_class = true
6
+ end
7
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bulkrax
4
+ class CsvCollectionEntry < CsvEntry
5
+ def factory_class
6
+ Collection
7
+ end
8
+
9
+ def build_metadata
10
+ self.parsed_metadata = self.raw_metadata
11
+ add_local
12
+ return self.parsed_metadata
13
+ end
14
+
15
+ def collections_created?
16
+ true
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,163 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'csv'
4
+
5
+ module Bulkrax
6
+ class CsvEntry < Entry
7
+ serialize :raw_metadata, JSON
8
+
9
+ def self.fields_from_data(data)
10
+ data.headers.flatten.compact.uniq
11
+ end
12
+
13
+ # there's a risk that this reads the whole file into memory and could cause a memory leak
14
+ def self.read_data(path)
15
+ raise StandardError, 'CSV path empty' if path.blank?
16
+ CSV.read(path,
17
+ headers: true,
18
+ header_converters: :symbol,
19
+ encoding: 'utf-8')
20
+ end
21
+
22
+ def self.data_for_entry(data, _source_id)
23
+ # If a multi-line CSV data is passed, grab the first row
24
+ data = data.first if data.is_a?(CSV::Table)
25
+ # model has to be separated so that it doesn't get mistranslated by to_h
26
+ raw_data = data.to_h
27
+ raw_data[:model] = data[:model]
28
+ # If the collection field mapping is not 'collection', add 'collection' - the parser needs it
29
+ raw_data[:collection] = raw_data[collection_field.to_sym] if raw_data.keys.include?(collection_field.to_sym) && collection_field != 'collection'
30
+ # If the children field mapping is not 'children', add 'children' - the parser needs it
31
+ raw_data[:children] = raw_data[collection_field.to_sym] if raw_data.keys.include?(children_field.to_sym) && children_field != 'children'
32
+ return raw_data
33
+ end
34
+
35
+ def self.collection_field
36
+ Bulkrax.collection_field_mapping[self.class.to_s] || 'collection'
37
+ end
38
+
39
+ def self.children_field
40
+ Bulkrax.parent_child_field_mapping[self.to_s] || 'children'
41
+ end
42
+
43
+ def keys_without_numbers(keys)
44
+ keys.map { |key| key_without_numbers(key) }
45
+ end
46
+
47
+ def key_without_numbers(key)
48
+ key.gsub(/_\d+/, '').sub(/^\d+_/, '')
49
+ end
50
+
51
+ def build_metadata
52
+ raise StandardError, 'Record not found' if record.nil?
53
+ raise StandardError, "Missing required elements, missing element(s) are: #{importerexporter.parser.missing_elements(keys_without_numbers(record.keys)).join(', ')}" unless importerexporter.parser.required_elements?(keys_without_numbers(record.keys))
54
+
55
+ self.parsed_metadata = {}
56
+ self.parsed_metadata[work_identifier] = [record[source_identifier]]
57
+ record.each do |key, value|
58
+ next if key == 'collection'
59
+
60
+ index = key[/\d+/].to_i - 1 if key[/\d+/].to_i != 0
61
+ add_metadata(key_without_numbers(key), value, index)
62
+ end
63
+ add_file
64
+ add_visibility
65
+ add_rights_statement
66
+ add_admin_set_id
67
+ add_collections
68
+ add_local
69
+ self.parsed_metadata
70
+ end
71
+
72
+ def add_file
73
+ self.parsed_metadata['file'] ||= []
74
+ if record['file']&.is_a?(String)
75
+ self.parsed_metadata['file'] = record['file'].split(/\s*[;|]\s*/)
76
+ elsif record['file'].is_a?(Array)
77
+ self.parsed_metadata['file'] = record['file']
78
+ end
79
+ self.parsed_metadata['file'] = self.parsed_metadata['file'].map { |f| path_to_file(f.tr(' ', '_')) }
80
+ end
81
+
82
+ def build_export_metadata
83
+ # make_round_trippable
84
+ self.parsed_metadata = {}
85
+ self.parsed_metadata['id'] = hyrax_record.id
86
+ self.parsed_metadata[source_identifier] = hyrax_record.send(work_identifier)
87
+ self.parsed_metadata['model'] = hyrax_record.has_model.first
88
+ build_mapping_metadata
89
+ self.parsed_metadata['collections'] = hyrax_record.member_of_collection_ids.join('; ')
90
+ unless hyrax_record.is_a?(Collection)
91
+ self.parsed_metadata['file'] = hyrax_record.file_sets.map { |fs| filename(fs).to_s if filename(fs).present? }.compact.join('; ')
92
+ end
93
+ self.parsed_metadata
94
+ end
95
+
96
+ def build_mapping_metadata
97
+ mapping.each do |key, value|
98
+ next if Bulkrax.reserved_properties.include?(key) && !field_supported?(key)
99
+ next if key == "model"
100
+ next unless hyrax_record.respond_to?(key.to_s)
101
+ data = hyrax_record.send(key.to_s)
102
+ if data.is_a?(ActiveTriples::Relation)
103
+ self.parsed_metadata[key] = data.map { |d| prepare_export_data(d) }.join('; ').to_s unless value[:excluded]
104
+ else
105
+ self.parsed_metadata[key] = prepare_export_data(data)
106
+ end
107
+ end
108
+ end
109
+
110
+ def prepare_export_data(datum)
111
+ if datum.is_a?(ActiveTriples::Resource)
112
+ datum.to_uri.to_s
113
+ else
114
+ datum
115
+ end
116
+ end
117
+
118
+ # In order for the existing exported hyrax_record, to be updated by a re-import
119
+ # we need a unique value in system_identifier
120
+ # add the existing hyrax_record id to system_identifier
121
+ def make_round_trippable
122
+ values = hyrax_record.send(work_identifier.to_s).to_a
123
+ values << hyrax_record.id
124
+ hyrax_record.send("#{work_identifier}=", values)
125
+ hyrax_record.save
126
+ end
127
+
128
+ def record
129
+ @record ||= raw_metadata
130
+ end
131
+
132
+ def self.matcher_class
133
+ Bulkrax::CsvMatcher
134
+ end
135
+
136
+ def collections_created?
137
+ return true if record[self.class.collection_field].blank?
138
+ record[self.class.collection_field].split(/\s*[:;|]\s*/).length == self.collection_ids.length
139
+ end
140
+
141
+ def find_or_create_collection_ids
142
+ return self.collection_ids if collections_created?
143
+ valid_system_id(Collection)
144
+ if record[self.class.collection_field].present?
145
+ record[self.class.collection_field].split(/\s*[:;|]\s*/).each do |collection|
146
+ c = find_collection(collection)
147
+ self.collection_ids << c.id unless c.blank? || self.collection_ids.include?(c.id)
148
+ end
149
+ end
150
+ self.collection_ids
151
+ end
152
+
153
+ # If only filename is given, construct the path (/files/my_file)
154
+ def path_to_file(file)
155
+ # return if we already have the full file path
156
+ return file if File.exist?(file)
157
+ path = importerexporter.parser.path_to_files
158
+ f = File.join(path, file)
159
+ return f if File.exist?(f)
160
+ raise "File #{f} does not exist"
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bulkrax
4
+ # Custom error class for collections_created?
5
+ class CollectionsCreatedError < RuntimeError; end
6
+ class OAIError < RuntimeError; end
7
+ class Entry < ApplicationRecord
8
+ include Bulkrax::HasMatchers
9
+ include Bulkrax::ImportBehavior
10
+ include Bulkrax::ExportBehavior
11
+ include Bulkrax::StatusInfo
12
+ include Bulkrax::HasLocalProcessing
13
+
14
+ belongs_to :importerexporter, polymorphic: true
15
+ alias importer importerexporter
16
+ alias exporter importerexporter
17
+
18
+ serialize :parsed_metadata, JSON
19
+ # Do not serialize raw_metadata as so we can support xml or other formats
20
+ serialize :collection_ids, Array
21
+
22
+ paginates_per 5
23
+
24
+ attr_accessor :all_attrs
25
+
26
+ delegate :parser, :mapping, :replace_files, :update_files, to: :importerexporter
27
+
28
+ delegate :client,
29
+ :collection_name,
30
+ :user,
31
+ to: :parser
32
+
33
+ # Retrieve fields from the file
34
+ # @param data - the source data
35
+ # @return Array
36
+ def self.fields_from_data(_data)
37
+ raise StandardError, 'Not Implemented'
38
+ end
39
+
40
+ # Read the data from the supplied path
41
+ # @param path - path to the data file
42
+ # @return the data from the file
43
+ def self.read_data(_path)
44
+ raise StandardError, 'Not Implemented'
45
+ end
46
+
47
+ # Returns formatted data from the given file for a single Entry
48
+ # @param data - the data from the metadata file
49
+ # @param path - the path to the metadata file (used by some entries to get the file_paths for import)
50
+ # @return Hash containing the data (the entry build_metadata method will know what to expect in the hash)
51
+ def self.data_for_entry(_data, _source_id)
52
+ raise StandardError, 'Not Implemented'
53
+ end
54
+
55
+ def source_identifier
56
+ parser&.source_identifier&.to_s || 'source_identifier'
57
+ end
58
+
59
+ def work_identifier
60
+ parser&.work_identifier&.to_s || 'source'
61
+ end
62
+
63
+ def self.collection_field
64
+ Bulkrax.collection_field_mapping[self.to_s]
65
+ end
66
+
67
+ def self.children_field
68
+ Bulkrax.parent_child_field_mapping[self.to_s]
69
+ end
70
+
71
+ def build
72
+ return if type.nil?
73
+ self.save if self.new_record? # must be saved for statuses
74
+
75
+ return build_for_importer if importer?
76
+ return build_for_exporter if exporter?
77
+ end
78
+
79
+ def importer?
80
+ self.importerexporter_type == 'Bulkrax::Importer'
81
+ end
82
+
83
+ def exporter?
84
+ self.importerexporter_type == 'Bulkrax::Exporter'
85
+ end
86
+
87
+ def valid_system_id(model_class)
88
+ return true if model_class.properties.keys.include?(work_identifier)
89
+ raise(
90
+ "#{model_class} does not implement the system_identifier_field: #{work_identifier}"
91
+ )
92
+ end
93
+
94
+ def last_run
95
+ self.importerexporter&.last_run
96
+ end
97
+
98
+ def find_collection(collection_identifier)
99
+ Collection.where(
100
+ work_identifier => collection_identifier
101
+ ).detect { |m| m.send(work_identifier).include?(collection_identifier) }
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+ module Bulkrax
3
+ class Exporter < ApplicationRecord
4
+ include Bulkrax::ImporterExporterBehavior
5
+ include Bulkrax::StatusInfo
6
+
7
+ serialize :parser_fields, JSON
8
+ serialize :field_mapping, JSON
9
+
10
+ belongs_to :user
11
+ has_many :exporter_runs, dependent: :destroy
12
+ has_many :entries, as: :importerexporter, dependent: :destroy
13
+
14
+ validates :name, presence: true
15
+ validates :parser_klass, presence: true
16
+
17
+ delegate :write, :create_from_collection, :create_from_importer, :create_from_worktype, to: :parser
18
+
19
+ def export
20
+ current_run && setup_export_path
21
+ case self.export_from
22
+ when 'collection'
23
+ create_from_collection
24
+ when 'importer'
25
+ create_from_importer
26
+ when 'worktype'
27
+ create_from_worktype
28
+ end
29
+ rescue StandardError => e
30
+ status_info(e)
31
+ end
32
+
33
+ # #export_source accessors
34
+ # Used in form to prevent it from getting confused as to which value to populate #export_source with.
35
+ # Also, used to display the correct selected value when rendering edit form.
36
+ def export_source_importer
37
+ self.export_source if self.export_from == 'importer'
38
+ end
39
+
40
+ def export_source_collection
41
+ self.export_source if self.export_from == 'collection'
42
+ end
43
+
44
+ def export_source_worktype
45
+ self.export_source if self.export_from == 'worktype'
46
+ end
47
+
48
+ def date_filter
49
+ self.start_date.present? || self.finish_date.present?
50
+ end
51
+
52
+ def work_visibility_list
53
+ [
54
+ ['Any', ''],
55
+ [I18n.t('hyrax.visibility.open.text'), Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC],
56
+ [I18n.t('hyrax.visibility.restricted.text'), Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE],
57
+ [I18n.t('hyrax.visibility.authenticated.text', institution: I18n.t('hyrax.institution_name')), Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED]
58
+ ]
59
+ end
60
+
61
+ def workflow_status_list
62
+ Sipity::WorkflowState.all.map { |s| [s.name&.titleize, s.name] }.uniq
63
+ end
64
+
65
+ # If field_mapping is empty, setup a default based on the export_properties
66
+ def mapping
67
+ @mapping ||= self.field_mapping ||
68
+ ActiveSupport::HashWithIndifferentAccess.new(
69
+ export_properties.map do |m|
70
+ Bulkrax.default_field_mapping.call(m)
71
+ end.inject(:merge)
72
+ ) ||
73
+ [{}]
74
+ end
75
+
76
+ def export_from_list
77
+ [
78
+ [I18n.t('bulkrax.exporter.labels.importer'), 'importer'],
79
+ [I18n.t('bulkrax.exporter.labels.collection'), 'collection'],
80
+ [I18n.t('bulkrax.exporter.labels.worktype'), 'worktype']
81
+ ]
82
+ end
83
+
84
+ def export_type_list
85
+ [
86
+ [I18n.t('bulkrax.exporter.labels.metadata'), 'metadata'],
87
+ [I18n.t('bulkrax.exporter.labels.full'), 'full']
88
+ ]
89
+ end
90
+
91
+ def importers_list
92
+ Importer.all.map { |i| [i.name, i.id] }
93
+ end
94
+
95
+ def current_run
96
+ @current_run ||= self.exporter_runs.create!(total_work_entries: self.limit || parser.total)
97
+ end
98
+
99
+ def last_run
100
+ @last_run ||= self.exporter_runs.last
101
+ end
102
+
103
+ def setup_export_path
104
+ FileUtils.mkdir_p(exporter_export_path) unless File.exist?(exporter_export_path)
105
+ end
106
+
107
+ def exporter_export_path
108
+ @exporter_export_path ||= File.join(Bulkrax.export_path, self.id.to_s, self.exporter_runs.last.id.to_s)
109
+ end
110
+
111
+ def exporter_export_zip_path
112
+ @exporter_export_zip_path ||= File.join(Bulkrax.export_path, "export_#{self.id}_#{self.exporter_runs.last.id}.zip")
113
+ rescue
114
+ @exporter_export_zip_path ||= File.join(Bulkrax.export_path, "export_#{self.id}_0.zip")
115
+ end
116
+
117
+ def export_properties
118
+ properties = Hyrax.config.registered_curation_concern_types.map { |work| work.constantize.properties.keys }.flatten.uniq.sort
119
+ properties.reject { |prop| Bulkrax.reserved_properties.include?(prop) }
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bulkrax
4
+ class ExporterRun < ApplicationRecord
5
+ belongs_to :exporter
6
+ end
7
+ end