bulkrax 6.0.1 → 7.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.
- checksums.yaml +4 -4
- data/Rakefile +7 -7
- data/app/assets/javascripts/bulkrax/bulkrax.js +11 -0
- data/app/assets/javascripts/bulkrax/datatables.js +139 -0
- data/app/assets/javascripts/bulkrax/exporters.js +4 -4
- data/app/assets/javascripts/bulkrax/importers.js.erb +15 -1
- data/app/assets/stylesheets/bulkrax/import_export.scss +6 -1
- data/app/controllers/bulkrax/entries_controller.rb +52 -3
- data/app/controllers/bulkrax/exporters_controller.rb +19 -7
- data/app/controllers/bulkrax/importers_controller.rb +29 -11
- data/app/controllers/concerns/bulkrax/datatables_behavior.rb +201 -0
- data/app/helpers/bulkrax/application_helper.rb +7 -3
- data/app/jobs/bulkrax/create_relationships_job.rb +1 -1
- data/app/jobs/bulkrax/delete_and_import_collection_job.rb +8 -0
- data/app/jobs/bulkrax/delete_and_import_file_set_job.rb +8 -0
- data/app/jobs/bulkrax/delete_and_import_job.rb +20 -0
- data/app/jobs/bulkrax/delete_and_import_work_job.rb +8 -0
- data/app/jobs/bulkrax/delete_job.rb +5 -1
- data/app/jobs/bulkrax/download_cloud_file_job.rb +1 -1
- data/app/jobs/bulkrax/import_collection_job.rb +1 -1
- data/app/jobs/bulkrax/import_file_set_job.rb +1 -1
- data/app/jobs/bulkrax/import_job.rb +7 -0
- data/app/jobs/bulkrax/import_work_job.rb +1 -1
- data/app/jobs/bulkrax/importer_job.rb +1 -1
- data/app/models/bulkrax/csv_collection_entry.rb +1 -3
- data/app/models/bulkrax/csv_entry.rb +2 -1
- data/app/models/bulkrax/entry.rb +2 -0
- data/app/models/bulkrax/exporter.rb +9 -2
- data/app/models/bulkrax/importer.rb +48 -7
- data/app/models/bulkrax/oai_set_entry.rb +1 -3
- data/app/models/bulkrax/rdf_collection_entry.rb +1 -4
- data/app/models/bulkrax/status.rb +10 -1
- data/app/models/concerns/bulkrax/file_set_entry_behavior.rb +4 -2
- data/app/models/concerns/bulkrax/import_behavior.rb +4 -16
- data/app/models/concerns/bulkrax/status_info.rb +8 -0
- data/app/parsers/bulkrax/application_parser.rb +90 -19
- data/app/parsers/bulkrax/bagit_parser.rb +0 -23
- data/app/parsers/bulkrax/csv_parser.rb +0 -52
- data/app/parsers/bulkrax/oai_dc_parser.rb +26 -16
- data/app/parsers/bulkrax/parser_export_record_set.rb +2 -2
- data/app/parsers/bulkrax/xml_parser.rb +18 -21
- data/app/services/bulkrax/factory_class_finder.rb +90 -0
- data/app/views/bulkrax/exporters/_form.html.erb +10 -10
- data/app/views/bulkrax/exporters/index.html.erb +13 -57
- data/app/views/bulkrax/exporters/show.html.erb +2 -10
- data/app/views/bulkrax/importers/_csv_fields.html.erb +7 -1
- data/app/views/bulkrax/importers/_edit_form_buttons.html.erb +8 -1
- data/app/views/bulkrax/importers/_edit_item_buttons.html.erb +18 -0
- data/app/views/bulkrax/importers/index.html.erb +20 -64
- data/app/views/bulkrax/importers/show.html.erb +7 -13
- data/app/views/bulkrax/shared/_entries_tab.html.erb +16 -0
- data/config/routes.rb +8 -2
- data/db/migrate/20240208005801_denormalize_status_message.rb +7 -0
- data/db/migrate/20240209070952_update_identifier_index.rb +6 -0
- data/lib/bulkrax/engine.rb +6 -0
- data/lib/bulkrax/persistence_layer/active_fedora_adapter.rb +27 -0
- data/lib/bulkrax/persistence_layer/valkyrie_adapter.rb +8 -0
- data/lib/bulkrax/persistence_layer.rb +38 -0
- data/lib/bulkrax/version.rb +1 -1
- data/lib/bulkrax.rb +88 -2
- data/lib/tasks/bulkrax_tasks.rake +12 -0
- metadata +46 -6
- data/app/views/bulkrax/shared/_collection_entries_tab.html.erb +0 -39
- data/app/views/bulkrax/shared/_file_set_entries_tab.html.erb +0 -39
- data/app/views/bulkrax/shared/_work_entries_tab.html.erb +0 -39
@@ -14,7 +14,7 @@ module Bulkrax
|
|
14
14
|
:seen, :increment_counters, :parser_fields, :user, :keys_without_numbers,
|
15
15
|
:key_without_numbers, :status, :set_status_info, :status_info, :status_at,
|
16
16
|
:exporter_export_path, :exporter_export_zip_path, :importer_unzip_path, :validate_only,
|
17
|
-
:zip?, :file?,
|
17
|
+
:zip?, :file?, :remove_and_rerun,
|
18
18
|
to: :importerexporter
|
19
19
|
|
20
20
|
# @todo Convert to `class_attribute :parser_fiels, default: {}`
|
@@ -47,6 +47,10 @@ module Bulkrax
|
|
47
47
|
raise NotImplementedError, 'must be defined'
|
48
48
|
end
|
49
49
|
|
50
|
+
def work_entry_class
|
51
|
+
entry_class
|
52
|
+
end
|
53
|
+
|
50
54
|
# @api public
|
51
55
|
# @abstract Subclass and override {#collection_entry_class} to implement behavior for the parser.
|
52
56
|
def collection_entry_class
|
@@ -157,6 +161,22 @@ module Bulkrax
|
|
157
161
|
@visibility ||= self.parser_fields['visibility'] || 'open'
|
158
162
|
end
|
159
163
|
|
164
|
+
def create_collections
|
165
|
+
create_objects(['collection'])
|
166
|
+
end
|
167
|
+
|
168
|
+
def create_works
|
169
|
+
create_objects(['work'])
|
170
|
+
end
|
171
|
+
|
172
|
+
def create_file_sets
|
173
|
+
create_objects(['file_set'])
|
174
|
+
end
|
175
|
+
|
176
|
+
def create_relationships
|
177
|
+
create_objects(['relationship'])
|
178
|
+
end
|
179
|
+
|
160
180
|
# @api public
|
161
181
|
#
|
162
182
|
# @param types [Array<Symbol>] the types of objects that we'll create.
|
@@ -166,30 +186,77 @@ module Bulkrax
|
|
166
186
|
# @see #create_works
|
167
187
|
# @see #create_file_sets
|
168
188
|
# @see #create_relationships
|
169
|
-
def create_objects(
|
170
|
-
|
171
|
-
|
189
|
+
def create_objects(types_array = nil)
|
190
|
+
index = 0
|
191
|
+
(types_array || %w[collection work file_set relationship]).each do |type|
|
192
|
+
if type.eql?('relationship')
|
193
|
+
ScheduleRelationshipsJob.set(wait: 5.minutes).perform_later(importer_id: importerexporter.id)
|
194
|
+
next
|
195
|
+
end
|
196
|
+
send(type.pluralize).each do |current_record|
|
197
|
+
next unless record_has_source_identifier(current_record, index)
|
198
|
+
break if limit_reached?(limit, index)
|
199
|
+
seen[current_record[source_identifier]] = true
|
200
|
+
create_entry_and_job(current_record, type)
|
201
|
+
increment_counters(index, "#{type}": true)
|
202
|
+
index += 1
|
203
|
+
end
|
204
|
+
importer.record_status
|
205
|
+
end
|
206
|
+
true
|
207
|
+
rescue StandardError => e
|
208
|
+
set_status_info(e)
|
209
|
+
end
|
210
|
+
|
211
|
+
def rebuild_entries(types_array = nil)
|
212
|
+
index = 0
|
213
|
+
(types_array || %w[collection work file_set relationship]).each do |type|
|
214
|
+
# works are not gurneteed to have Work in the type
|
215
|
+
|
216
|
+
importer.entries.where(rebuild_entry_query(type, parser_fields['entry_statuses'])).find_each do |e|
|
217
|
+
seen[e.identifier] = true
|
218
|
+
e.status_info('Pending', importer.current_run)
|
219
|
+
if remove_and_rerun
|
220
|
+
delay = calculate_type_delay(type)
|
221
|
+
"Bulkrax::DeleteAndImport#{type.camelize}Job".constantize.set(wait: delay).send(perform_method, e, current_run)
|
222
|
+
else
|
223
|
+
"Bulkrax::Import#{type.camelize}Job".constantize.send(perform_method, e.id, current_run.id)
|
224
|
+
end
|
225
|
+
increment_counters(index)
|
226
|
+
index += 1
|
227
|
+
end
|
172
228
|
end
|
173
229
|
end
|
174
230
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
end
|
231
|
+
def rebuild_entry_query(type, statuses)
|
232
|
+
type_col = Bulkrax::Entry.arel_table['type']
|
233
|
+
status_col = Bulkrax::Entry.arel_table['status_message']
|
179
234
|
|
180
|
-
|
181
|
-
|
182
|
-
raise NotImplementedError, 'must be defined' if importer?
|
235
|
+
query = (type == 'work' ? type_col.not.matches(%w[collection file_set]) : type_col.matches(type.camelize))
|
236
|
+
query.and(status_col.in(statuses))
|
183
237
|
end
|
184
238
|
|
185
|
-
|
186
|
-
|
187
|
-
|
239
|
+
def calculate_type_delay(type)
|
240
|
+
return 2.minutes if type == 'file_set'
|
241
|
+
return 1.minute if type == 'work'
|
242
|
+
return 0
|
188
243
|
end
|
189
244
|
|
190
|
-
|
191
|
-
|
192
|
-
|
245
|
+
def create_entry_and_job(current_record, type, identifier = nil)
|
246
|
+
identifier ||= current_record[source_identifier]
|
247
|
+
new_entry = find_or_create_entry(send("#{type}_entry_class"),
|
248
|
+
identifier,
|
249
|
+
'Bulkrax::Importer',
|
250
|
+
current_record.to_h)
|
251
|
+
new_entry.status_info('Pending', importer.current_run)
|
252
|
+
if current_record[:delete].present?
|
253
|
+
"Bulkrax::Delete#{type.camelize}Job".constantize.send(perform_method, new_entry, current_run)
|
254
|
+
elsif current_record[:remove_and_rerun].present? || remove_and_rerun
|
255
|
+
delay = calculate_type_delay(type)
|
256
|
+
"Bulkrax::DeleteAndImport#{type.camelize}Job".constantize.set(wait: delay).send(perform_method, new_entry, current_run)
|
257
|
+
else
|
258
|
+
"Bulkrax::Import#{type.camelize}Job".constantize.send(perform_method, new_entry.id, current_run.id)
|
259
|
+
end
|
193
260
|
end
|
194
261
|
|
195
262
|
# Optional, define if using browse everything for file upload
|
@@ -305,11 +372,15 @@ module Bulkrax
|
|
305
372
|
end
|
306
373
|
|
307
374
|
def find_or_create_entry(entryclass, identifier, type, raw_metadata = nil)
|
308
|
-
entry
|
375
|
+
# limit entry search to just this importer or exporter. Don't go moving them
|
376
|
+
entry = importerexporter.entries.where(
|
377
|
+
identifier: identifier
|
378
|
+
).first
|
379
|
+
entry ||= entryclass.new(
|
309
380
|
importerexporter_id: importerexporter.id,
|
310
381
|
importerexporter_type: type,
|
311
382
|
identifier: identifier
|
312
|
-
)
|
383
|
+
)
|
313
384
|
entry.raw_metadata = raw_metadata
|
314
385
|
entry.save!
|
315
386
|
entry
|
@@ -63,29 +63,6 @@ module Bulkrax
|
|
63
63
|
data
|
64
64
|
end
|
65
65
|
|
66
|
-
def create_works
|
67
|
-
entry_class == CsvEntry ? super : create_rdf_works
|
68
|
-
end
|
69
|
-
|
70
|
-
def create_rdf_works
|
71
|
-
records.each_with_index do |record, index|
|
72
|
-
next unless record_has_source_identifier(record, index)
|
73
|
-
break if limit_reached?(limit, index)
|
74
|
-
|
75
|
-
seen[record[source_identifier]] = true
|
76
|
-
new_entry = find_or_create_entry(entry_class, record[source_identifier], 'Bulkrax::Importer', record)
|
77
|
-
if record[:delete].present?
|
78
|
-
DeleteWorkJob.send(perform_method, new_entry, current_run)
|
79
|
-
else
|
80
|
-
ImportWorkJob.send(perform_method, new_entry.id, current_run.id)
|
81
|
-
end
|
82
|
-
increment_counters(index, work: true)
|
83
|
-
end
|
84
|
-
importer.record_status
|
85
|
-
rescue StandardError => e
|
86
|
-
set_status_info(e)
|
87
|
-
end
|
88
|
-
|
89
66
|
# export methods
|
90
67
|
|
91
68
|
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
@@ -113,57 +113,6 @@ module Bulkrax
|
|
113
113
|
false
|
114
114
|
end
|
115
115
|
|
116
|
-
def create_collections
|
117
|
-
create_objects(['collection'])
|
118
|
-
end
|
119
|
-
|
120
|
-
def create_works
|
121
|
-
create_objects(['work'])
|
122
|
-
end
|
123
|
-
|
124
|
-
def create_file_sets
|
125
|
-
create_objects(['file_set'])
|
126
|
-
end
|
127
|
-
|
128
|
-
def create_relationships
|
129
|
-
create_objects(['relationship'])
|
130
|
-
end
|
131
|
-
|
132
|
-
def create_objects(types_array = nil)
|
133
|
-
index = 0
|
134
|
-
(types_array || %w[collection work file_set relationship]).each do |type|
|
135
|
-
if type.eql?('relationship')
|
136
|
-
ScheduleRelationshipsJob.set(wait: 5.minutes).perform_later(importer_id: importerexporter.id)
|
137
|
-
next
|
138
|
-
end
|
139
|
-
send(type.pluralize).each do |current_record|
|
140
|
-
next unless record_has_source_identifier(current_record, index)
|
141
|
-
break if limit_reached?(limit, index)
|
142
|
-
|
143
|
-
seen[current_record[source_identifier]] = true
|
144
|
-
create_entry_and_job(current_record, type)
|
145
|
-
increment_counters(index, "#{type}": true)
|
146
|
-
index += 1
|
147
|
-
end
|
148
|
-
importer.record_status
|
149
|
-
end
|
150
|
-
true
|
151
|
-
rescue StandardError => e
|
152
|
-
set_status_info(e)
|
153
|
-
end
|
154
|
-
|
155
|
-
def create_entry_and_job(current_record, type)
|
156
|
-
new_entry = find_or_create_entry(send("#{type}_entry_class"),
|
157
|
-
current_record[source_identifier],
|
158
|
-
'Bulkrax::Importer',
|
159
|
-
current_record.to_h)
|
160
|
-
if current_record[:delete].present?
|
161
|
-
"Bulkrax::Delete#{type.camelize}Job".constantize.send(perform_method, new_entry, current_run)
|
162
|
-
else
|
163
|
-
"Bulkrax::Import#{type.camelize}Job".constantize.send(perform_method, new_entry.id, current_run.id)
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
116
|
def write_partial_import_file(file)
|
168
117
|
import_filename = import_file_path.split('/').last
|
169
118
|
partial_import_filename = "#{File.basename(import_filename, '.csv')}_corrected_entries.csv"
|
@@ -204,7 +153,6 @@ module Bulkrax
|
|
204
153
|
def entry_class
|
205
154
|
CsvEntry
|
206
155
|
end
|
207
|
-
alias work_entry_class entry_class
|
208
156
|
|
209
157
|
def collection_entry_class
|
210
158
|
CsvCollectionEntry
|
@@ -63,6 +63,12 @@ module Bulkrax
|
|
63
63
|
|
64
64
|
delegate :list_sets, to: :client
|
65
65
|
|
66
|
+
def create_objects(types = [])
|
67
|
+
types.each do |object_type|
|
68
|
+
send("create_#{object_type.pluralize}")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
66
72
|
def create_collections
|
67
73
|
metadata = {
|
68
74
|
visibility: 'open'
|
@@ -86,27 +92,31 @@ module Bulkrax
|
|
86
92
|
results = self.records(quick: true)
|
87
93
|
return if results.blank?
|
88
94
|
results.full.each_with_index do |record, index|
|
89
|
-
identifier = record
|
90
|
-
|
91
|
-
if Bulkrax.fill_in_blank_source_identifiers.present?
|
92
|
-
identifier = Bulkrax.fill_in_blank_source_identifiers.call(self, index)
|
93
|
-
else
|
94
|
-
invalid_record("Missing #{source_identifier} for #{record.to_h}\n")
|
95
|
-
next
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
95
|
+
identifier = record_has_source_identifier(record, index)
|
96
|
+
next unless identifier
|
99
97
|
break if limit_reached?(limit, index)
|
98
|
+
|
100
99
|
seen[identifier] = true
|
101
|
-
|
102
|
-
if record.deleted?
|
103
|
-
DeleteWorkJob.send(perform_method, new_entry, importerexporter.current_run)
|
104
|
-
else
|
105
|
-
ImportWorkJob.send(perform_method, new_entry.id, importerexporter.current_run.id)
|
106
|
-
end
|
100
|
+
create_entry_and_job(record, 'work', identifier)
|
107
101
|
increment_counters(index, work: true)
|
108
102
|
end
|
109
103
|
importer.record_status
|
104
|
+
rescue StandardError => e
|
105
|
+
set_status_info(e)
|
106
|
+
end
|
107
|
+
|
108
|
+
# oai records so not let us set the source identifier easily
|
109
|
+
def record_has_source_identifier(record, index)
|
110
|
+
identifier = record.send(source_identifier)
|
111
|
+
if identifier.blank?
|
112
|
+
if Bulkrax.fill_in_blank_source_identifiers.present?
|
113
|
+
identifier = Bulkrax.fill_in_blank_source_identifiers.call(self, index)
|
114
|
+
else
|
115
|
+
invalid_record("Missing #{source_identifier} for #{record.to_h}\n")
|
116
|
+
return false
|
117
|
+
end
|
118
|
+
end
|
119
|
+
identifier
|
110
120
|
end
|
111
121
|
|
112
122
|
def collections
|
@@ -113,14 +113,14 @@ module Bulkrax
|
|
113
113
|
#
|
114
114
|
# @see #file_sets
|
115
115
|
def candidate_file_set_ids
|
116
|
-
@candidate_file_set_ids ||= works.flat_map { |work| work.fetch(
|
116
|
+
@candidate_file_set_ids ||= works.flat_map { |work| work.fetch(Bulkrax.solr_key_for_member_file_ids, []) }
|
117
117
|
end
|
118
118
|
|
119
119
|
# @note Specifically not memoizing this so we can merge values without changing the object.
|
120
120
|
#
|
121
121
|
# No sense attempting to query for more than the limit.
|
122
122
|
def query_kwargs
|
123
|
-
{ fl: "id,#{Bulkrax.
|
123
|
+
{ fl: "id,#{Bulkrax.solr_key_for_member_file_ids}", method: :post, rows: row_limit }
|
124
124
|
end
|
125
125
|
|
126
126
|
# If we have a limit, we need not query beyond that limit
|
@@ -11,13 +11,29 @@ module Bulkrax
|
|
11
11
|
def collection_entry_class; end
|
12
12
|
|
13
13
|
# @todo not yet supported
|
14
|
-
def create_collections
|
14
|
+
def create_collections
|
15
|
+
raise NotImplementedError
|
16
|
+
end
|
15
17
|
|
16
18
|
# @todo not yet supported
|
17
19
|
def file_set_entry_class; end
|
18
20
|
|
19
21
|
# @todo not yet supported
|
20
|
-
def create_file_sets
|
22
|
+
def create_file_sets
|
23
|
+
raise NotImplementedError
|
24
|
+
end
|
25
|
+
|
26
|
+
def file_sets
|
27
|
+
raise NotImplementedError
|
28
|
+
end
|
29
|
+
|
30
|
+
def collections
|
31
|
+
raise NotImplementedError
|
32
|
+
end
|
33
|
+
|
34
|
+
def works
|
35
|
+
records
|
36
|
+
end
|
21
37
|
|
22
38
|
# TODO: change to differentiate between collection and work records when adding ability to import collection metadata
|
23
39
|
def works_total
|
@@ -92,25 +108,6 @@ module Bulkrax
|
|
92
108
|
%w[.xml .xls .xsd].include?(File.extname(path)) || ::Marcel::MimeType.for(path).include?('application/xml')
|
93
109
|
end
|
94
110
|
|
95
|
-
def create_works
|
96
|
-
records.each_with_index do |record, index|
|
97
|
-
next unless record_has_source_identifier(record, index)
|
98
|
-
break if !limit.nil? && index >= limit
|
99
|
-
|
100
|
-
seen[record[source_identifier]] = true
|
101
|
-
new_entry = find_or_create_entry(entry_class, record[source_identifier], 'Bulkrax::Importer', record)
|
102
|
-
if record[:delete].present?
|
103
|
-
DeleteWorkJob.send(perform_method, new_entry, current_run)
|
104
|
-
else
|
105
|
-
ImportWorkJob.send(perform_method, new_entry.id, current_run.id)
|
106
|
-
end
|
107
|
-
increment_counters(index, work: true)
|
108
|
-
end
|
109
|
-
importer.record_status
|
110
|
-
rescue StandardError => e
|
111
|
-
set_status_info(e)
|
112
|
-
end
|
113
|
-
|
114
111
|
def total
|
115
112
|
records.size
|
116
113
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Bulkrax
|
4
|
+
class FactoryClassFinder
|
5
|
+
##
|
6
|
+
# The v6.0.0 default coercer. Responsible for converting a factory class name to a constant.
|
7
|
+
module DefaultCoercer
|
8
|
+
##
|
9
|
+
# @param name [String]
|
10
|
+
# @return [Class] when the name is a coercible constant.
|
11
|
+
# @raise [NameError] when the name is not coercible to a constant.
|
12
|
+
def self.call(name)
|
13
|
+
name.constantize
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# A name coercer that favors classes that end with "Resource" but will attempt to fallback to
|
19
|
+
# those that don't.
|
20
|
+
module ValkyrieMigrationCoercer
|
21
|
+
SUFFIX = "Resource"
|
22
|
+
|
23
|
+
##
|
24
|
+
# @param name [String]
|
25
|
+
# @param suffix [String] the suffix we use for a naming convention.
|
26
|
+
#
|
27
|
+
# @return [Class] when the name is a coercible constant.
|
28
|
+
# @raise [NameError] when the name is not coercible to a constant.
|
29
|
+
def self.call(name, suffix: SUFFIX)
|
30
|
+
if name.end_with?(suffix)
|
31
|
+
name.constantize
|
32
|
+
else
|
33
|
+
begin
|
34
|
+
"#{name}#{suffix}".constantize
|
35
|
+
rescue NameError
|
36
|
+
name.constantize
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# @param entry [Bulkrax::Entry]
|
44
|
+
# @return [Class]
|
45
|
+
def self.find(entry:, coercer: Bulkrax.factory_class_name_coercer || DefaultCoercer)
|
46
|
+
new(entry: entry, coercer: coercer).find
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialize(entry:, coercer:)
|
50
|
+
@entry = entry
|
51
|
+
@coercer = coercer
|
52
|
+
end
|
53
|
+
attr_reader :entry, :coercer
|
54
|
+
|
55
|
+
##
|
56
|
+
# @return [Class] when we are able to derive the class based on the {#name}.
|
57
|
+
# @return [Nil] when we encounter errors with constantizing the {#name}.
|
58
|
+
# @see #name
|
59
|
+
def find
|
60
|
+
coercer.call(name)
|
61
|
+
rescue NameError
|
62
|
+
nil
|
63
|
+
rescue
|
64
|
+
entry.default_work_type.constantize
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# @api private
|
69
|
+
# @return [String]
|
70
|
+
def name
|
71
|
+
fc = if entry.parsed_metadata&.[]('model').present?
|
72
|
+
Array.wrap(entry.parsed_metadata['model']).first
|
73
|
+
elsif entry.importerexporter&.mapping&.[]('work_type').present?
|
74
|
+
# Because of delegation's nil guard, we're reaching rather far into the implementation
|
75
|
+
# details.
|
76
|
+
Array.wrap(entry.parsed_metadata['work_type']).first
|
77
|
+
else
|
78
|
+
entry.default_work_type
|
79
|
+
end
|
80
|
+
|
81
|
+
# Let's coerce this into the right shape; we're not mutating the string because it might well
|
82
|
+
# be frozen.
|
83
|
+
fc = fc.tr(' ', '_')
|
84
|
+
fc = fc.downcase if fc.match?(/[-_]/)
|
85
|
+
fc.camelcase
|
86
|
+
rescue
|
87
|
+
entry.default_work_type
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -33,8 +33,8 @@
|
|
33
33
|
label: t('bulkrax.exporter.labels.importer'),
|
34
34
|
required: true,
|
35
35
|
prompt: 'Select from the list',
|
36
|
-
label_html: { class: 'importer export-source-option d-none' },
|
37
|
-
input_html: { class: 'importer export-source-option d-none form-control' },
|
36
|
+
label_html: { class: 'importer export-source-option d-none hidden' },
|
37
|
+
input_html: { class: 'importer export-source-option d-none hidden form-control' },
|
38
38
|
collection: form.object.importers_list.sort %>
|
39
39
|
|
40
40
|
<%= form.input :export_source_collection,
|
@@ -42,9 +42,9 @@
|
|
42
42
|
label: t('bulkrax.exporter.labels.collection'),
|
43
43
|
required: true,
|
44
44
|
placeholder: @collection&.title&.first,
|
45
|
-
label_html: { class: 'collection export-source-option d-none' },
|
45
|
+
label_html: { class: 'collection export-source-option d-none hidden' },
|
46
46
|
input_html: {
|
47
|
-
class: 'collection export-source-option d-none form-control',
|
47
|
+
class: 'collection export-source-option d-none hidden form-control',
|
48
48
|
data: {
|
49
49
|
'autocomplete-url' => '/authorities/search/collections',
|
50
50
|
'autocomplete' => 'collection'
|
@@ -56,8 +56,8 @@
|
|
56
56
|
label: t('bulkrax.exporter.labels.worktype'),
|
57
57
|
required: true,
|
58
58
|
prompt: 'Select from the list',
|
59
|
-
label_html: { class: 'worktype export-source-option d-none' },
|
60
|
-
input_html: { class: 'worktype export-source-option d-none form-control' },
|
59
|
+
label_html: { class: 'worktype export-source-option d-none hidden' },
|
60
|
+
input_html: { class: 'worktype export-source-option d-none hidden form-control' },
|
61
61
|
collection: Bulkrax.curation_concerns.map { |cc| [cc.to_s, cc.to_s] } %>
|
62
62
|
|
63
63
|
<%= form.input :limit,
|
@@ -80,7 +80,7 @@
|
|
80
80
|
as: :boolean,
|
81
81
|
label: t('bulkrax.exporter.labels.filter_by_date') %>
|
82
82
|
|
83
|
-
<div id="date_filter_picker" class="d-none">
|
83
|
+
<div id="date_filter_picker" class="d-none hidden">
|
84
84
|
<%= form.input :start_date,
|
85
85
|
as: :date,
|
86
86
|
label: t('bulkrax.exporter.labels.start_date'),
|
@@ -136,13 +136,13 @@
|
|
136
136
|
// get the date filter option and show the corresponding date selectors
|
137
137
|
$('.exporter_date_filter').change(function () {
|
138
138
|
if ($('.exporter_date_filter').find(".boolean").is(":checked"))
|
139
|
-
$('#date_filter_picker').removeClass('d-none');
|
139
|
+
$('#date_filter_picker').removeClass('d-none hidden');
|
140
140
|
else
|
141
|
-
$('#date_filter_picker').addClass('d-none');
|
141
|
+
$('#date_filter_picker').addClass('d-none hidden');
|
142
142
|
});
|
143
143
|
|
144
144
|
if ($('.exporter_date_filter').find(".boolean").is(":checked"))
|
145
|
-
$('#date_filter_picker').removeClass('d-none');
|
145
|
+
$('#date_filter_picker').removeClass('d-none hidden');
|
146
146
|
});
|
147
147
|
});
|
148
148
|
</script>
|
@@ -13,62 +13,18 @@
|
|
13
13
|
|
14
14
|
<div class="panel panel-default">
|
15
15
|
<div class="panel-body">
|
16
|
-
|
17
|
-
<
|
18
|
-
<
|
19
|
-
<
|
20
|
-
<
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
</thead>
|
30
|
-
<tbody>
|
31
|
-
<% @exporters.each do |exporter| %>
|
32
|
-
<tr>
|
33
|
-
<th scope="row"><%= link_to exporter.name, exporter_path(exporter) %></th>
|
34
|
-
<td><%= exporter.status %></td>
|
35
|
-
<td><%= exporter.created_at %></td>
|
36
|
-
<td>
|
37
|
-
<% if File.exist?(exporter.exporter_export_zip_path) %>
|
38
|
-
<%= simple_form_for(exporter, method: :get, url: exporter_download_path(exporter)) do |form| %>
|
39
|
-
<%= render 'downloads', exporter: exporter, form: form %>
|
40
|
-
<%= form.button :submit, value: 'Download', data: { disable_with: false } %>
|
41
|
-
<% end %>
|
42
|
-
<% end%>
|
43
|
-
</td>
|
44
|
-
<td><%= link_to raw('<span class="glyphicon glyphicon-info-sign"></span>'), exporter_path(exporter) %></td>
|
45
|
-
<td><%= link_to raw('<span class="glyphicon glyphicon-pencil"></span>'), edit_exporter_path(exporter), data: { turbolinks: false } %></td>
|
46
|
-
<td><%= link_to raw('<span class="glyphicon glyphicon-remove"></span>'), exporter, method: :delete, data: { confirm: 'Are you sure?' } %></td>
|
47
|
-
</tr>
|
48
|
-
<% end %>
|
49
|
-
</tbody>
|
50
|
-
</table>
|
51
|
-
</div>
|
52
|
-
<% else %>
|
53
|
-
<p>No exporters have been created.</p>
|
54
|
-
<% end %>
|
16
|
+
<div class="table-responsive">
|
17
|
+
<table id='exporters-table' class="table table-striped">
|
18
|
+
<thead>
|
19
|
+
<tr>
|
20
|
+
<th scope="col">Name</th>
|
21
|
+
<th scope="col">Status</th>
|
22
|
+
<th scope="col">Date Exported</th>
|
23
|
+
<th scope="col">Downloadable Files</th>
|
24
|
+
<th scope="col">Actions</th>
|
25
|
+
</tr>
|
26
|
+
</thead>
|
27
|
+
</table>
|
28
|
+
</div>
|
55
29
|
</div>
|
56
30
|
</div>
|
57
|
-
|
58
|
-
<script>
|
59
|
-
$(function() {
|
60
|
-
$('#DataTables_Table_0').DataTable({
|
61
|
-
destroy: true, /* Reinitialize DataTable with config below */
|
62
|
-
'columnDefs': [
|
63
|
-
{ 'orderable': true, 'targets': [0, 1, 2] },
|
64
|
-
{ 'orderable': false, 'targets': [3, 4, 5, 6] }
|
65
|
-
],
|
66
|
-
'language': {
|
67
|
-
'info': 'Showing _START_ to _END_ of _TOTAL_ exporters',
|
68
|
-
'infoEmpty': 'No exporters to show',
|
69
|
-
'infoFiltered': '(filtered from _MAX_ total exporters)',
|
70
|
-
'lengthMenu': 'Show _MENU_ exporters'
|
71
|
-
}
|
72
|
-
})
|
73
|
-
})
|
74
|
-
</script>
|
@@ -95,16 +95,8 @@
|
|
95
95
|
|
96
96
|
<div class="bulkrax-nav-tab-bottom-margin">
|
97
97
|
<!-- Nav tabs -->
|
98
|
-
<
|
99
|
-
|
100
|
-
<li role="presentation" class="nav-link"><a href="#collection-entries" aria-controls="collection-entries" role="tab" data-toggle="tab"><%= t('bulkrax.exporter.labels.collection_entries') %></a></li>
|
101
|
-
<li role="presentation" class="nav-link"><a href="#file-set-entries" aria-controls="file-set-entries" role="tab" data-toggle="tab"><%= t('bulkrax.exporter.labels.file_set_entries') %></a></li>
|
102
|
-
</ul>
|
103
|
-
<!-- Tab panes -->
|
104
|
-
<div class="tab-content outline">
|
105
|
-
<%= render partial: 'bulkrax/shared/work_entries_tab', locals: { item: @exporter, entries: @work_entries } %>
|
106
|
-
<%= render partial: 'bulkrax/shared/collection_entries_tab', locals: { item: @exporter, entries: @collection_entries } %>
|
107
|
-
<%= render partial: 'bulkrax/shared/file_set_entries_tab', locals: { item: @exporter, entries: @file_set_entries } %>
|
98
|
+
<div class="outline">
|
99
|
+
<%= render partial: 'bulkrax/shared/entries_tab', locals: { item: @exporter } %>
|
108
100
|
</div>
|
109
101
|
<br>
|
110
102
|
<%= link_to 'Edit', edit_exporter_path(@exporter) %>
|
@@ -25,13 +25,19 @@
|
|
25
25
|
<h4>Add CSV File to Import:</h4>
|
26
26
|
<%# accept a single file upload; data files and bags will need to be added another way %>
|
27
27
|
|
28
|
-
|
28
|
+
<% file_style_list = ['Upload a File', 'Specify a Path on the Server'] %>
|
29
|
+
<% file_style_list << 'Existing Entries' unless importer.new_record? %>
|
30
|
+
<%= fi.input :file_style, collection: file_style_list, as: :radio_buttons, label: false %>
|
29
31
|
<div id='file_upload'>
|
30
32
|
<%= fi.input 'file', as: :file, input_html: { accept: 'text/csv,application/zip' } %><br />
|
31
33
|
</div>
|
32
34
|
<div id='file_path'>
|
33
35
|
<%= fi.input :import_file_path, as: :string, input_html: { value: importer.parser_fields['import_file_path'] } %>
|
34
36
|
</div>
|
37
|
+
<div id='existing_options'>
|
38
|
+
<%= fi.collection_check_boxes :entry_statuses, [['Failed'], ['Pending'], ['Skipped'], ['Deleted'], ['Complete']], :first, :first %>
|
39
|
+
</div>
|
40
|
+
|
35
41
|
<% if defined?(::Hyrax) && Hyrax.config.browse_everything? %>
|
36
42
|
<h4>Add Files to Import:</h4>
|
37
43
|
<p>Choose files to upload. The filenames must be unique, and the filenames must be referenced in a column called 'file' in the accompanying CSV file.</p>
|
@@ -34,7 +34,14 @@
|
|
34
34
|
<%= form.button :submit,
|
35
35
|
value: 'Update and Replace Files',
|
36
36
|
class: 'btn btn-primary',
|
37
|
-
|
37
|
+
data: {confirm: "Are you sure? This will remove all files before adding them from the import."} %>
|
38
|
+
<hr />
|
39
|
+
<p>Remove all works and then run the import again from a clean slate. This will remove all files and associations and any edits made since the last import will be lost.</p>
|
40
|
+
<%= form.button :submit,
|
41
|
+
value: 'Remove and Rerun',
|
42
|
+
class: 'btn btn-primary',
|
43
|
+
data: {confirm: "Are you sure? This will delete all the works and any associated files and relationships before re running."} %>
|
44
|
+
|
38
45
|
<% end %>
|
39
46
|
<hr />
|
40
47
|
|