bulkrax 6.0.0 → 7.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +93 -22
- 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
|
@@ -85,7 +89,7 @@ module Bulkrax
|
|
85
89
|
# defaults to work_identifier value + "_sim"
|
86
90
|
# @see #work_identifier
|
87
91
|
def work_identifier_search_field
|
88
|
-
@work_identifier_search_field ||= get_field_mapping_hash_for('source_identifier')&.values&.first&.[]('search_field')&.first&.to_s || "#{work_identifier}_sim"
|
92
|
+
@work_identifier_search_field ||= Array.wrap(get_field_mapping_hash_for('source_identifier')&.values&.first&.[]('search_field'))&.first&.to_s || "#{work_identifier}_sim"
|
89
93
|
end
|
90
94
|
|
91
95
|
# @return [String]
|
@@ -102,7 +106,7 @@ module Bulkrax
|
|
102
106
|
# @return [String]
|
103
107
|
# @see #related_parents_field_mapping
|
104
108
|
def related_parents_parsed_mapping
|
105
|
-
@related_parents_parsed_mapping ||=
|
109
|
+
@related_parents_parsed_mapping ||= get_field_mapping_hash_for('related_parents_field_mapping')&.keys&.first || 'parents'
|
106
110
|
end
|
107
111
|
|
108
112
|
# @return [String, NilClass]
|
@@ -114,7 +118,7 @@ module Bulkrax
|
|
114
118
|
# @return [String]
|
115
119
|
# @see #related_children_raw_mapping
|
116
120
|
def related_children_parsed_mapping
|
117
|
-
@related_children_parsed_mapping ||=
|
121
|
+
@related_children_parsed_mapping ||= get_field_mapping_hash_for('related_children_field_mapping')&.keys&.first || 'children'
|
118
122
|
end
|
119
123
|
|
120
124
|
# @api private
|
@@ -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) %>
|