bulkrax 9.3.4 → 9.4.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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +11 -1
  3. data/app/assets/javascripts/bulkrax/application.js +2 -1
  4. data/app/assets/javascripts/bulkrax/bulkrax.js +13 -4
  5. data/app/assets/javascripts/bulkrax/bulkrax_utils.js +96 -0
  6. data/app/assets/javascripts/bulkrax/datatables.js +1 -0
  7. data/app/assets/javascripts/bulkrax/entries.js +17 -10
  8. data/app/assets/javascripts/bulkrax/importers.js.erb +9 -2
  9. data/app/assets/javascripts/bulkrax/importers_stepper.js +2420 -0
  10. data/app/assets/stylesheets/bulkrax/application.css +1 -1
  11. data/app/assets/stylesheets/bulkrax/import_export.scss +9 -2
  12. data/app/assets/stylesheets/bulkrax/stepper/_header.scss +83 -0
  13. data/app/assets/stylesheets/bulkrax/stepper/_mixins.scss +26 -0
  14. data/app/assets/stylesheets/bulkrax/stepper/_navigation.scss +103 -0
  15. data/app/assets/stylesheets/bulkrax/stepper/_responsive.scss +46 -0
  16. data/app/assets/stylesheets/bulkrax/stepper/_review.scss +92 -0
  17. data/app/assets/stylesheets/bulkrax/stepper/_settings.scss +106 -0
  18. data/app/assets/stylesheets/bulkrax/stepper/_success.scss +26 -0
  19. data/app/assets/stylesheets/bulkrax/stepper/_summary.scss +171 -0
  20. data/app/assets/stylesheets/bulkrax/stepper/_upload.scss +339 -0
  21. data/app/assets/stylesheets/bulkrax/stepper/_validation.scss +237 -0
  22. data/app/assets/stylesheets/bulkrax/stepper/_variables.scss +46 -0
  23. data/app/assets/stylesheets/bulkrax/stepper.scss +32 -0
  24. data/app/controllers/bulkrax/guided_imports_controller.rb +175 -0
  25. data/app/controllers/bulkrax/importers_controller.rb +34 -28
  26. data/app/controllers/concerns/bulkrax/guided_import_demo_scenarios.rb +201 -0
  27. data/app/controllers/concerns/bulkrax/importer_file_handler.rb +217 -0
  28. data/app/factories/bulkrax/object_factory.rb +3 -2
  29. data/app/factories/bulkrax/valkyrie_object_factory.rb +61 -17
  30. data/app/jobs/bulkrax/export_work_job.rb +1 -3
  31. data/app/jobs/bulkrax/importer_job.rb +11 -4
  32. data/app/models/bulkrax/csv_entry.rb +27 -7
  33. data/app/models/bulkrax/entry.rb +4 -0
  34. data/app/models/bulkrax/importer.rb +31 -1
  35. data/app/models/concerns/bulkrax/has_matchers.rb +2 -2
  36. data/app/models/concerns/bulkrax/importer_exporter_behavior.rb +6 -5
  37. data/app/parsers/bulkrax/application_parser.rb +31 -5
  38. data/app/parsers/bulkrax/csv_parser.rb +42 -10
  39. data/app/parsers/concerns/bulkrax/csv_parser/csv_template_generation.rb +73 -0
  40. data/app/parsers/concerns/bulkrax/csv_parser/csv_validation.rb +133 -0
  41. data/app/parsers/concerns/bulkrax/csv_parser/csv_validation_helpers.rb +282 -0
  42. data/app/parsers/concerns/bulkrax/csv_parser/csv_validation_hierarchy.rb +96 -0
  43. data/app/services/bulkrax/csv_template/column_builder.rb +60 -0
  44. data/app/services/bulkrax/csv_template/column_descriptor.rb +58 -0
  45. data/app/services/bulkrax/csv_template/csv_builder.rb +83 -0
  46. data/app/services/bulkrax/csv_template/explanation_builder.rb +57 -0
  47. data/app/services/bulkrax/csv_template/field_analyzer.rb +56 -0
  48. data/app/services/bulkrax/csv_template/file_path_generator.rb +47 -0
  49. data/app/services/bulkrax/csv_template/file_validator.rb +68 -0
  50. data/app/services/bulkrax/csv_template/mapping_manager.rb +55 -0
  51. data/app/services/bulkrax/csv_template/model_loader.rb +50 -0
  52. data/app/services/bulkrax/csv_template/row_builder.rb +35 -0
  53. data/app/services/bulkrax/csv_template/schema_analyzer.rb +70 -0
  54. data/app/services/bulkrax/csv_template/split_formatter.rb +44 -0
  55. data/app/services/bulkrax/csv_template/value_determiner.rb +68 -0
  56. data/app/services/bulkrax/stepper_response_formatter.rb +347 -0
  57. data/app/services/bulkrax/validation_error_csv_builder.rb +99 -0
  58. data/app/validators/bulkrax/csv_row/child_reference.rb +56 -0
  59. data/app/validators/bulkrax/csv_row/circular_reference.rb +71 -0
  60. data/app/validators/bulkrax/csv_row/controlled_vocabulary.rb +74 -0
  61. data/app/validators/bulkrax/csv_row/duplicate_identifier.rb +63 -0
  62. data/app/validators/bulkrax/csv_row/missing_source_identifier.rb +31 -0
  63. data/app/validators/bulkrax/csv_row/parent_reference.rb +59 -0
  64. data/app/validators/bulkrax/csv_row/required_values.rb +64 -0
  65. data/app/views/bulkrax/entries/_parsed_metadata.html.erb +1 -1
  66. data/app/views/bulkrax/entries/_raw_metadata.html.erb +1 -1
  67. data/app/views/bulkrax/entries/show.html.erb +6 -6
  68. data/app/views/bulkrax/exporters/_form.html.erb +19 -43
  69. data/app/views/bulkrax/exporters/edit.html.erb +2 -2
  70. data/app/views/bulkrax/exporters/index.html.erb +5 -5
  71. data/app/views/bulkrax/exporters/new.html.erb +3 -5
  72. data/app/views/bulkrax/exporters/show.html.erb +3 -3
  73. data/app/views/bulkrax/guided_imports/new.html.erb +567 -0
  74. data/app/views/bulkrax/importers/_bagit_fields.html.erb +9 -9
  75. data/app/views/bulkrax/importers/_browse_everything.html.erb +1 -1
  76. data/app/views/bulkrax/importers/_csv_fields.html.erb +11 -11
  77. data/app/views/bulkrax/importers/_edit_form_buttons.html.erb +23 -23
  78. data/app/views/bulkrax/importers/_edit_item_buttons.html.erb +2 -2
  79. data/app/views/bulkrax/importers/_file_uploader.html.erb +3 -3
  80. data/app/views/bulkrax/importers/_form.html.erb +4 -5
  81. data/app/views/bulkrax/importers/_oai_fields.html.erb +8 -18
  82. data/app/views/bulkrax/importers/_xml_fields.html.erb +13 -13
  83. data/app/views/bulkrax/importers/edit.html.erb +2 -2
  84. data/app/views/bulkrax/importers/index.html.erb +19 -14
  85. data/app/views/bulkrax/importers/new.html.erb +10 -9
  86. data/app/views/bulkrax/importers/show.html.erb +23 -7
  87. data/app/views/bulkrax/importers/upload_corrected_entries.html.erb +6 -6
  88. data/app/views/bulkrax/shared/_bulkrax_errors.html.erb +11 -11
  89. data/app/views/bulkrax/shared/_bulkrax_field_mapping.html.erb +3 -3
  90. data/config/i18n-tasks.yml +195 -0
  91. data/config/locales/bulkrax.de.yml +504 -0
  92. data/config/locales/bulkrax.en.yml +487 -28
  93. data/config/locales/bulkrax.es.yml +504 -0
  94. data/config/locales/bulkrax.fr.yml +504 -0
  95. data/config/locales/bulkrax.it.yml +504 -0
  96. data/config/locales/bulkrax.pt-BR.yml +504 -0
  97. data/config/locales/bulkrax.zh.yml +503 -0
  98. data/config/routes.rb +10 -0
  99. data/lib/bulkrax/data/demo_scenarios.json +2235 -0
  100. data/lib/bulkrax/version.rb +1 -1
  101. data/lib/bulkrax.rb +31 -3
  102. data/lib/tasks/bulkrax_tasks.rake +0 -102
  103. metadata +55 -3
  104. /data/{app/services → lib}/wings/custom_queries/find_by_source_identifier.rb +0 -0
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bulkrax
4
- VERSION = '9.3.4'
4
+ VERSION = '9.4.0'
5
5
  end
data/lib/bulkrax.rb CHANGED
@@ -15,6 +15,8 @@ require 'nokogiri'
15
15
  require 'ostruct'
16
16
  require 'zip'
17
17
 
18
+ require 'wings/custom_queries/find_by_source_identifier'
19
+
18
20
  def conditional_require(gem_name)
19
21
  require gem_name
20
22
  rescue LoadError
@@ -37,6 +39,8 @@ module Bulkrax
37
39
  :default_work_type,
38
40
  :export_path,
39
41
  :field_mappings,
42
+ :guided_import_enabled,
43
+ :guided_import_demo_scenarios_enabled,
40
44
  :generated_metadata_mapping,
41
45
  :import_path,
42
46
  :multi_value_element_join_on,
@@ -170,6 +174,28 @@ module Bulkrax
170
174
  ENV.key?("REDIS_HOST")
171
175
  end
172
176
  alias use_locking? use_locking
177
+
178
+ ##
179
+ # @return [Array<#call>] callable validators invoked per-row during CSV validation.
180
+ # Each callable receives (record, row_number, context).
181
+ # Defaults to the four built-in CsvRow:: validators.
182
+ def csv_row_validators
183
+ @csv_row_validators ||= [
184
+ Bulkrax::CsvRow::MissingSourceIdentifier,
185
+ Bulkrax::CsvRow::DuplicateIdentifier,
186
+ Bulkrax::CsvRow::ParentReference,
187
+ Bulkrax::CsvRow::ChildReference,
188
+ Bulkrax::CsvRow::CircularReference,
189
+ Bulkrax::CsvRow::RequiredValues,
190
+ Bulkrax::CsvRow::ControlledVocabulary
191
+ ]
192
+ end
193
+
194
+ attr_writer :csv_row_validators
195
+
196
+ def register_csv_row_validator(callable)
197
+ csv_row_validators << callable
198
+ end
173
199
  end
174
200
 
175
201
  def config
@@ -180,7 +206,6 @@ module Bulkrax
180
206
  alias setup config
181
207
 
182
208
  def_delegators :@config,
183
- :api_definition,
184
209
  :api_definition=,
185
210
  :collection_model_class,
186
211
  :collection_model_internal_resource,
@@ -207,9 +232,7 @@ module Bulkrax
207
232
  :generated_metadata_mapping=,
208
233
  :import_path,
209
234
  :import_path=,
210
- :multi_value_element_join_on,
211
235
  :multi_value_element_join_on=,
212
- :multi_value_element_split_on,
213
236
  :multi_value_element_split_on=,
214
237
  :object_factory,
215
238
  :object_factory=,
@@ -229,6 +252,9 @@ module Bulkrax
229
252
  :required_elements=,
230
253
  :reserved_properties,
231
254
  :reserved_properties=,
255
+ :csv_row_validators,
256
+ :csv_row_validators=,
257
+ :register_csv_row_validator,
232
258
  :server_name,
233
259
  :server_name=,
234
260
  :solr_key_for_member_file_ids,
@@ -252,6 +278,8 @@ module Bulkrax
252
278
  conf.server_name = 'bulkrax@example.com'
253
279
  conf.relationship_job_class = "Bulkrax::CreateRelationshipsJob"
254
280
  conf.required_elements = ['title']
281
+ conf.guided_import_enabled = ActiveModel::Type::Boolean.new.cast(ENV.fetch('BULKRAX_GUIDED_IMPORTER', false))
282
+ conf.guided_import_demo_scenarios_enabled = false
255
283
 
256
284
  # Hash of Generic field_mappings for use in the view
257
285
  # There must be one field_mappings hash per view partial
@@ -14,108 +14,6 @@ namespace :bulkrax do
14
14
  end
15
15
  end
16
16
 
17
- # Usage example: rails bulkrax:generate_test_csvs['5','100','GenericWork']
18
- desc 'Generate CSVs with fake data for testing purposes'
19
- task :generate_test_csvs, [:num_of_csvs, :csv_rows, :record_type] => :environment do |_t, args|
20
- # NOTE: If this line throws an error, run `gem install faker` inside your Docker container
21
- require 'faker'
22
- require 'csv'
23
-
24
- FileUtils.mkdir_p(Rails.root.join('tmp', 'imports'))
25
-
26
- IGNORED_PROPERTIES = %w[
27
- admin_set_id
28
- alternate_ids
29
- arkivo_checksum
30
- created_at
31
- date_modified
32
- date_uploaded
33
- depositor
34
- embargo
35
- has_model
36
- head
37
- internal_resource
38
- label
39
- lease
40
- member_ids
41
- member_of_collection_ids
42
- modified_date
43
- new_record
44
- on_behalf_of
45
- owner
46
- proxy_depositor
47
- rendering_ids
48
- representative_id
49
- state
50
- tail
51
- thumbnail_id
52
- updated_at
53
- ].freeze
54
-
55
- BULKRAX_PROPERTIES = %w[
56
- source_identifier
57
- model
58
- ].freeze
59
-
60
- num_of_csvs = args.num_of_csvs.presence&.to_i || 5
61
- csv_rows = args.csv_rows.presence&.to_i || 100
62
- record_type = args.record_type.presence&.constantize || GenericWork
63
-
64
- csv_header = if Hyrax.config.try(:use_valkyrie?)
65
- record_type.schema.map { |k| k.name.to_s }
66
- else
67
- record_type.properties.keys
68
- end
69
-
70
- csv_header -= IGNORED_PROPERTIES
71
- csv_header.unshift(*BULKRAX_PROPERTIES)
72
-
73
- num_of_csvs.times do |i|
74
- CSV.open(Rails.root.join('tmp', 'imports', "importer_#{i}.csv"), 'wb') do |csv|
75
- csv << csv_header
76
- csv_rows.times do |_index|
77
- row = []
78
- csv_header.each do |prop_name|
79
- row << case prop_name
80
- when 'id', 'source_identifier'
81
- Faker::Number.number(digits: 4)
82
- when 'model'
83
- record_type.to_s
84
- when 'rights_statement'
85
- 'http://rightsstatements.org/vocab/CNE/1.0/'
86
- when 'license'
87
- 'https://creativecommons.org/licenses/by-nc/4.0/'
88
- when 'based_near'
89
- # FIXME: Set a proper :based_near value
90
- nil
91
- else
92
- Faker::Lorem.sentence
93
- end
94
- end
95
- csv << row
96
- end
97
- end
98
- end
99
-
100
- num_of_csvs.times do |i|
101
- Bulkrax::Importer.create(
102
- name: "Generated CSV #{i}",
103
- admin_set_id: 'admin_set/default',
104
- user_id: User.find_by(email: 'admin@example.com').id,
105
- frequency: 'PT0S',
106
- parser_klass: 'Bulkrax::CsvParser',
107
- parser_fields: {
108
- 'visibility' => 'open',
109
- 'rights_statement' => '',
110
- 'override_rights_statement' => '0',
111
- 'file_style' => 'Specify a Path on the Server',
112
- 'import_file_path' => "tmp/imports/importer_#{i}.csv",
113
- 'update_files' => false
114
- }
115
- )
116
- end
117
- end
118
-
119
17
  desc "Remove old exported zips and create new ones with the new file structure"
120
18
  task rerun_all_exporters: :environment do
121
19
  # delete the existing folders and zip files
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bulkrax
3
3
  version: !ruby/object:Gem::Version
4
- version: 9.3.4
4
+ version: 9.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob Kaufman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-01-15 00:00:00.000000000 Z
11
+ date: 2026-04-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -331,23 +331,40 @@ files:
331
331
  - app/assets/config/bulkrax_manifest.js
332
332
  - app/assets/javascripts/bulkrax/application.js
333
333
  - app/assets/javascripts/bulkrax/bulkrax.js
334
+ - app/assets/javascripts/bulkrax/bulkrax_utils.js
334
335
  - app/assets/javascripts/bulkrax/datatables.js
335
336
  - app/assets/javascripts/bulkrax/entries.js
336
337
  - app/assets/javascripts/bulkrax/exporters.js
337
338
  - app/assets/javascripts/bulkrax/importers.js.erb
339
+ - app/assets/javascripts/bulkrax/importers_stepper.js
338
340
  - app/assets/javascripts/bulkrax/navtabs.js.erb
339
341
  - app/assets/stylesheets/bulkrax/accordion.scss
340
342
  - app/assets/stylesheets/bulkrax/application.css
341
343
  - app/assets/stylesheets/bulkrax/coderay.scss
342
344
  - app/assets/stylesheets/bulkrax/import_export.scss
345
+ - app/assets/stylesheets/bulkrax/stepper.scss
346
+ - app/assets/stylesheets/bulkrax/stepper/_header.scss
347
+ - app/assets/stylesheets/bulkrax/stepper/_mixins.scss
348
+ - app/assets/stylesheets/bulkrax/stepper/_navigation.scss
349
+ - app/assets/stylesheets/bulkrax/stepper/_responsive.scss
350
+ - app/assets/stylesheets/bulkrax/stepper/_review.scss
351
+ - app/assets/stylesheets/bulkrax/stepper/_settings.scss
352
+ - app/assets/stylesheets/bulkrax/stepper/_success.scss
353
+ - app/assets/stylesheets/bulkrax/stepper/_summary.scss
354
+ - app/assets/stylesheets/bulkrax/stepper/_upload.scss
355
+ - app/assets/stylesheets/bulkrax/stepper/_validation.scss
356
+ - app/assets/stylesheets/bulkrax/stepper/_variables.scss
343
357
  - app/concerns/loggable.rb
344
358
  - app/controllers/bulkrax/application_controller.rb
345
359
  - app/controllers/bulkrax/entries_controller.rb
346
360
  - app/controllers/bulkrax/exporters_controller.rb
361
+ - app/controllers/bulkrax/guided_imports_controller.rb
347
362
  - app/controllers/bulkrax/importers_controller.rb
348
363
  - app/controllers/concerns/bulkrax/api.rb
349
364
  - app/controllers/concerns/bulkrax/datatables_behavior.rb
350
365
  - app/controllers/concerns/bulkrax/download_behavior.rb
366
+ - app/controllers/concerns/bulkrax/guided_import_demo_scenarios.rb
367
+ - app/controllers/concerns/bulkrax/importer_file_handler.rb
351
368
  - app/factories/bulkrax/object_factory.rb
352
369
  - app/factories/bulkrax/object_factory_interface.rb
353
370
  - app/factories/bulkrax/valkyrie_object_factory.rb
@@ -416,10 +433,35 @@ files:
416
433
  - app/parsers/bulkrax/oai_qualified_dc_parser.rb
417
434
  - app/parsers/bulkrax/parser_export_record_set.rb
418
435
  - app/parsers/bulkrax/xml_parser.rb
436
+ - app/parsers/concerns/bulkrax/csv_parser/csv_template_generation.rb
437
+ - app/parsers/concerns/bulkrax/csv_parser/csv_validation.rb
438
+ - app/parsers/concerns/bulkrax/csv_parser/csv_validation_helpers.rb
439
+ - app/parsers/concerns/bulkrax/csv_parser/csv_validation_hierarchy.rb
440
+ - app/services/bulkrax/csv_template/column_builder.rb
441
+ - app/services/bulkrax/csv_template/column_descriptor.rb
442
+ - app/services/bulkrax/csv_template/csv_builder.rb
443
+ - app/services/bulkrax/csv_template/explanation_builder.rb
444
+ - app/services/bulkrax/csv_template/field_analyzer.rb
445
+ - app/services/bulkrax/csv_template/file_path_generator.rb
446
+ - app/services/bulkrax/csv_template/file_validator.rb
447
+ - app/services/bulkrax/csv_template/mapping_manager.rb
448
+ - app/services/bulkrax/csv_template/model_loader.rb
449
+ - app/services/bulkrax/csv_template/row_builder.rb
450
+ - app/services/bulkrax/csv_template/schema_analyzer.rb
451
+ - app/services/bulkrax/csv_template/split_formatter.rb
452
+ - app/services/bulkrax/csv_template/value_determiner.rb
419
453
  - app/services/bulkrax/factory_class_finder.rb
420
454
  - app/services/bulkrax/remove_relationships_for_importer.rb
455
+ - app/services/bulkrax/stepper_response_formatter.rb
456
+ - app/services/bulkrax/validation_error_csv_builder.rb
421
457
  - app/services/hyrax/custom_queries/find_by_source_identifier.rb
422
- - app/services/wings/custom_queries/find_by_source_identifier.rb
458
+ - app/validators/bulkrax/csv_row/child_reference.rb
459
+ - app/validators/bulkrax/csv_row/circular_reference.rb
460
+ - app/validators/bulkrax/csv_row/controlled_vocabulary.rb
461
+ - app/validators/bulkrax/csv_row/duplicate_identifier.rb
462
+ - app/validators/bulkrax/csv_row/missing_source_identifier.rb
463
+ - app/validators/bulkrax/csv_row/parent_reference.rb
464
+ - app/validators/bulkrax/csv_row/required_values.rb
423
465
  - app/views/bulkrax/entries/_parsed_metadata.html.erb
424
466
  - app/views/bulkrax/entries/_raw_metadata.html.erb
425
467
  - app/views/bulkrax/entries/show.html.erb
@@ -429,6 +471,7 @@ files:
429
471
  - app/views/bulkrax/exporters/index.html.erb
430
472
  - app/views/bulkrax/exporters/new.html.erb
431
473
  - app/views/bulkrax/exporters/show.html.erb
474
+ - app/views/bulkrax/guided_imports/new.html.erb
432
475
  - app/views/bulkrax/importers/_bagit_fields.html.erb
433
476
  - app/views/bulkrax/importers/_browse_everything.html.erb
434
477
  - app/views/bulkrax/importers/_csv_fields.html.erb
@@ -449,7 +492,14 @@ files:
449
492
  - app/views/hyrax/dashboard/sidebar/_bulkrax_sidebar_additions.html.erb
450
493
  - app/views/hyrax/dashboard/sidebar/_repository_content.html.erb
451
494
  - app/views/layouts/bulkrax/application.html.erb
495
+ - config/i18n-tasks.yml
496
+ - config/locales/bulkrax.de.yml
452
497
  - config/locales/bulkrax.en.yml
498
+ - config/locales/bulkrax.es.yml
499
+ - config/locales/bulkrax.fr.yml
500
+ - config/locales/bulkrax.it.yml
501
+ - config/locales/bulkrax.pt-BR.yml
502
+ - config/locales/bulkrax.zh.yml
453
503
  - config/routes.rb
454
504
  - db/migrate/20181011230201_create_bulkrax_importers.rb
455
505
  - db/migrate/20181011230228_create_bulkrax_importer_runs.rb
@@ -496,6 +546,7 @@ files:
496
546
  - db/migrate/20241203010707_entry_error_denormalization.rb
497
547
  - db/migrate/20241205212513_faster_first_entry.rb
498
548
  - lib/bulkrax.rb
549
+ - lib/bulkrax/data/demo_scenarios.json
499
550
  - lib/bulkrax/engine.rb
500
551
  - lib/bulkrax/entry_spec_helper.rb
501
552
  - lib/bulkrax/version.rb
@@ -508,6 +559,7 @@ files:
508
559
  - lib/generators/bulkrax/templates/config/initializers/bulkrax.rb
509
560
  - lib/tasks/bulkrax_tasks.rake
510
561
  - lib/tasks/reset.rake
562
+ - lib/wings/custom_queries/find_by_source_identifier.rb
511
563
  homepage: https://github.com/samvera-labs/bulkrax
512
564
  licenses:
513
565
  - Apache-2.0