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,37 @@
1
+ div.importer_parser_fields_file_style span.radio {
2
+ display: inline;
3
+ margin-right: 20px;
4
+ }
5
+
6
+ div#file_upload, div#file_path {
7
+ display: none;
8
+ }
9
+
10
+ div.hide-required-tag .required-tag {
11
+ display: none;
12
+ }
13
+
14
+ div#s2id_exporter_export_source_collection {
15
+ border: none;
16
+ padding: 0;
17
+ }
18
+
19
+ .bulkrax-nav-tab-top-margin {
20
+ margin-top: 20px !important;
21
+ }
22
+
23
+ .bulkrax-nav-tab-bottom-margin {
24
+ margin-bottom: 20px;
25
+ }
26
+
27
+ .bulkrax-nav-tab-table-left-align {
28
+ margin-left: 10px;
29
+ }
30
+
31
+ .bulkrax-p-align {
32
+ margin: 15px 0 10px 15px;
33
+ }
34
+
35
+ .bulkrax-clear-toggles {
36
+ clear: both;
37
+ }
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bulkrax
4
+ class ApplicationController < ::ApplicationController
5
+ helper Rails.application.class.helpers
6
+ protect_from_forgery with: :exception
7
+ end
8
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency "bulkrax/application_controller"
4
+ require_dependency "oai"
5
+
6
+ module Bulkrax
7
+ class EntriesController < ApplicationController
8
+ include Hyrax::ThemedLayoutController
9
+ before_action :authenticate_user!
10
+ with_themed_layout 'dashboard'
11
+
12
+ def show
13
+ if params[:importer_id].present?
14
+ show_importer
15
+ elsif params[:exporter_id].present?
16
+ show_exporter
17
+ end
18
+ end
19
+
20
+ # GET /importers/1/entries/1
21
+ def show_importer
22
+ @importer = Importer.find(params[:importer_id])
23
+ @entry = Entry.find(params[:id])
24
+
25
+ add_breadcrumb t(:'hyrax.controls.home'), main_app.root_path
26
+ add_breadcrumb t(:'hyrax.dashboard.breadcrumbs.admin'), hyrax.dashboard_path
27
+ add_breadcrumb 'Importers', bulkrax.importers_path
28
+ add_breadcrumb @importer.name, bulkrax.importer_path(@importer.id)
29
+ add_breadcrumb @entry.id
30
+ end
31
+
32
+ # GET /exporters/1/entries/1
33
+ def show_exporter
34
+ @exporter = Exporter.find(params[:exporter_id])
35
+ @entry = Entry.find(params[:id])
36
+
37
+ add_breadcrumb t(:'hyrax.controls.home'), main_app.root_path
38
+ add_breadcrumb t(:'hyrax.dashboard.breadcrumbs.admin'), hyrax.dashboard_path
39
+ add_breadcrumb 'Exporters', bulkrax.exporters_path
40
+ add_breadcrumb @exporter.name, bulkrax.exporter_path(@exporter.id)
41
+ add_breadcrumb @entry.id
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency "bulkrax/application_controller"
4
+
5
+ module Bulkrax
6
+ class ExportersController < ApplicationController
7
+ include Hyrax::ThemedLayoutController
8
+ include Bulkrax::DownloadBehavior
9
+ before_action :authenticate_user!
10
+ before_action :set_exporter, only: [:show, :edit, :update, :destroy]
11
+ with_themed_layout 'dashboard'
12
+
13
+ # GET /exporters
14
+ def index
15
+ @exporters = Exporter.all
16
+
17
+ add_exporter_breadcrumbs
18
+ end
19
+
20
+ # GET /exporters/1
21
+ def show
22
+ add_exporter_breadcrumbs
23
+ add_breadcrumb @exporter.name
24
+
25
+ @work_entries = @exporter.entries.where(type: @exporter.parser.entry_class.to_s).page(params[:work_entries_page])
26
+ end
27
+
28
+ # GET /exporters/new
29
+ def new
30
+ @exporter = Exporter.new
31
+
32
+ add_exporter_breadcrumbs
33
+ add_breadcrumb 'New'
34
+ end
35
+
36
+ # GET /exporters/1/edit
37
+ def edit
38
+ add_exporter_breadcrumbs
39
+ add_breadcrumb @exporter.name, bulkrax.exporter_path(@exporter.id)
40
+ add_breadcrumb 'Edit'
41
+
42
+ # Correctly populate export_source_collection input
43
+ @collection = Collection.find(@exporter.export_source) if @exporter.export_source.present? && @exporter.export_from == 'collection'
44
+ end
45
+
46
+ # POST /exporters
47
+ def create
48
+ @exporter = Exporter.new(exporter_params)
49
+ field_mapping_params
50
+
51
+ if @exporter.save
52
+ if params[:commit] == 'Create and Export'
53
+ # Use perform now for export
54
+ Bulkrax::ExporterJob.perform_now(@exporter.id)
55
+ end
56
+ redirect_to exporters_path, notice: 'Exporter was successfully created.'
57
+ else
58
+ render :new
59
+ end
60
+ end
61
+
62
+ # PATCH/PUT /exporters/1
63
+ def update
64
+ field_mapping_params
65
+ if @exporter.update(exporter_params)
66
+ Bulkrax::ExporterJob.perform_now(@exporter.id) if params[:commit] == 'Update and Re-Export All Items'
67
+ redirect_to exporters_path, notice: 'Exporter was successfully updated.'
68
+ else
69
+ render :edit
70
+ end
71
+ end
72
+
73
+ # DELETE /exporters/1
74
+ def destroy
75
+ @exporter.destroy
76
+ redirect_to exporters_url, notice: 'Exporter was successfully destroyed.'
77
+ end
78
+
79
+ # GET /exporters/1/download
80
+ def download
81
+ @exporter = Exporter.find(params[:exporter_id])
82
+ send_content
83
+ end
84
+
85
+ private
86
+
87
+ # Use callbacks to share common setup or constraints between actions.
88
+ def set_exporter
89
+ @exporter = Exporter.find(params[:id])
90
+ end
91
+
92
+ # Only allow a trusted parameters through.
93
+ def exporter_params
94
+ params[:exporter][:export_source] = params[:exporter]["export_source_#{params[:exporter][:export_from]}".to_sym]
95
+ if params[:exporter][:date_filter] == "1"
96
+ params.fetch(:exporter).permit(:name, :user_id, :export_source, :export_from, :export_type,
97
+ :parser_klass, :limit, :start_date, :finish_date, :work_visibility,
98
+ :workflow_status, field_mapping: {})
99
+ else
100
+ params.fetch(:exporter).permit(:name, :user_id, :export_source, :export_from, :export_type,
101
+ :parser_klass, :limit, :work_visibility, :workflow_status,
102
+ field_mapping: {}).merge(start_date: nil, finish_date: nil)
103
+ end
104
+ end
105
+
106
+ # Add the field_mapping from the Bulkrax configuration
107
+ def field_mapping_params
108
+ # @todo replace/append once mapping GUI is in place
109
+ field_mapping_key = Bulkrax.parsers.map { |m| m[:class_name] if m[:class_name] == params[:exporter][:parser_klass] }.compact.first
110
+ @exporter.field_mapping = Bulkrax.field_mappings[field_mapping_key] if field_mapping_key
111
+ end
112
+
113
+ def add_exporter_breadcrumbs
114
+ add_breadcrumb t(:'hyrax.controls.home'), main_app.root_path
115
+ add_breadcrumb t(:'hyrax.dashboard.breadcrumbs.admin'), hyrax.dashboard_path
116
+ add_breadcrumb 'Exporters', bulkrax.exporters_path
117
+ end
118
+
119
+ # Download methods
120
+
121
+ def file_path
122
+ @exporter.exporter_export_zip_path
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,315 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency 'bulkrax/application_controller'
4
+ require_dependency 'oai'
5
+
6
+ module Bulkrax
7
+ # rubocop:disable Metrics/ClassLength
8
+ class ImportersController < ApplicationController
9
+ include Hyrax::ThemedLayoutController
10
+ include Bulkrax::DownloadBehavior
11
+ include Bulkrax::API
12
+ include Bulkrax::ValidationHelper
13
+
14
+ protect_from_forgery unless: -> { api_request? }
15
+ before_action :token_authenticate!, if: -> { api_request? }, only: [:create, :update, :delete]
16
+ before_action :authenticate_user!, unless: -> { api_request? }
17
+ before_action :set_importer, only: [:show, :edit, :update, :destroy]
18
+ with_themed_layout 'dashboard'
19
+
20
+ # GET /importers
21
+ def index
22
+ @importers = Importer.all
23
+ if api_request?
24
+ json_response('index')
25
+ else
26
+ add_importer_breadcrumbs
27
+ end
28
+ end
29
+
30
+ # GET /importers/1
31
+ def show
32
+ if api_request?
33
+ json_response('show')
34
+ else
35
+ add_importer_breadcrumbs
36
+ add_breadcrumb @importer.name
37
+
38
+ @work_entries = @importer.entries.where(type: @importer.parser.entry_class.to_s).page(params[:work_entries_page]).per(30)
39
+ @collection_entries = @importer.entries.where(type: @importer.parser.collection_entry_class.to_s).page(params[:collections_entries_page]).per(30)
40
+ end
41
+ end
42
+
43
+ # GET /importers/new
44
+ def new
45
+ @importer = Importer.new
46
+ if api_request?
47
+ json_response('new')
48
+ else
49
+ add_importer_breadcrumbs
50
+ add_breadcrumb 'New'
51
+ end
52
+ end
53
+
54
+ # GET /importers/1/edit
55
+ def edit
56
+ if api_request?
57
+ json_response('edit')
58
+ else
59
+ add_importer_breadcrumbs
60
+ add_breadcrumb @importer.name, bulkrax.importer_path(@importer.id)
61
+ add_breadcrumb 'Edit'
62
+ end
63
+ end
64
+
65
+ # POST /importers
66
+ # rubocop:disable Metrics/MethodLength
67
+ def create
68
+ # rubocop:disable Style/IfInsideElse
69
+ if api_request?
70
+ return return_json_response unless valid_create_params?
71
+ end
72
+ file = file_param
73
+ cloud_files = cloud_params
74
+
75
+ @importer = Importer.new(importer_params)
76
+ field_mapping_params
77
+ @importer.validate_only = true if params[:commit] == 'Create and Validate'
78
+ if @importer.save
79
+ files_for_import(file, cloud_files)
80
+ if params[:commit] == 'Create and Import'
81
+ Bulkrax::ImporterJob.send(@importer.parser.perform_method, @importer.id)
82
+ render_request('Importer was successfully created and import has been queued.')
83
+ elsif params[:commit] == 'Create and Validate'
84
+ Bulkrax::ImporterJob.send(@importer.parser.perform_method, @importer.id)
85
+ render_request('Importer validation completed. Please review and choose to either Continue with or Discard the import.', true)
86
+ else
87
+ render_request('Importer was successfully created.')
88
+ end
89
+ else
90
+ if api_request?
91
+ json_response('create', :unprocessable_entity)
92
+ else
93
+ render :new
94
+ end
95
+ end
96
+ # rubocop:enable Style/IfInsideElse
97
+ end
98
+
99
+ # PATCH/PUT /importers/1
100
+ # # @todo refactor so as to not need to disable rubocop
101
+ # rubocop:disable all
102
+ def update
103
+ if api_request?
104
+ return return_json_response unless valid_update_params?
105
+ end
106
+
107
+ file = file_param
108
+ cloud_files = cloud_params
109
+
110
+ # Skipped during a continue
111
+ field_mapping_params if params[:importer][:parser_fields].present?
112
+
113
+ if @importer.update(importer_params)
114
+ files_for_import(file, cloud_files) unless file.nil? && cloud_files.nil?
115
+ # do not perform the import
116
+ if params[:commit] == 'Update Importer'
117
+ # do nothing
118
+ # OAI-only - selective re-harvest
119
+ elsif params[:commit] == 'Update and Harvest Updated Items'
120
+ Bulkrax::ImporterJob.perform_later(@importer.id, true)
121
+ elsif params[:commit] == 'Update All (update metadata and update files)'
122
+ @importer.parser_fields['update_files'] = true
123
+ @importer.save
124
+ Bulkrax::ImporterJob.perform_later(@importer.id)
125
+ # Perform a full metadata and files re-import; do the same for an OAI re-harvest of all items
126
+ elsif params[:commit] == ('Update and Replace (update metadata and replace files)' || 'Update and Re-Harvest All Items')
127
+ @importer.parser_fields['replace_files'] = true
128
+ @importer.save
129
+ Bulkrax::ImporterJob.perform_later(@importer.id)
130
+ # In all other cases, perform a metadata-only re-import
131
+ else
132
+ Bulkrax::ImporterJob.perform_later(@importer.id)
133
+ end
134
+ if api_request?
135
+ json_response('updated', :ok, 'Importer was successfully updated.')
136
+ else
137
+ redirect_to importers_path, notice: 'Importer was successfully updated.'
138
+ end
139
+ else
140
+ if api_request?
141
+ json_response('update', :unprocessable_entity, 'Something went wrong.')
142
+ else
143
+ render :edit
144
+ end
145
+ end
146
+ end
147
+ # rubocop:enable all
148
+ # rubocop:enable Metrics/MethodLength
149
+
150
+ # DELETE /importers/1
151
+ def destroy
152
+ @importer.destroy
153
+ if api_request?
154
+ json_response('destroy', :ok, notice: 'Importer was successfully destroyed.')
155
+ else
156
+ redirect_to importers_url, notice: 'Importer was successfully destroyed.'
157
+ end
158
+ end
159
+
160
+ # PUT /importers/1
161
+ def continue
162
+ @importer = Importer.find(params[:importer_id])
163
+ params[:importer] = { name: @importer.name }
164
+ @importer.validate_only = false
165
+ update
166
+ end
167
+
168
+ # GET /importer/1/upload_corrected_entries
169
+ def upload_corrected_entries
170
+ @importer = Importer.find(params[:importer_id])
171
+ add_breadcrumb t(:'hyrax.controls.home'), main_app.root_path
172
+ add_breadcrumb t(:'hyrax.dashboard.breadcrumbs.admin'), hyrax.dashboard_path
173
+ add_breadcrumb 'Importers', bulkrax.importers_path
174
+ add_breadcrumb @importer.name, bulkrax.importer_path(@importer.id)
175
+ add_breadcrumb 'Upload Corrected Entries'
176
+ end
177
+
178
+ # POST /importer/1/upload_corrected_entries_file
179
+ def upload_corrected_entries_file
180
+ file = params[:importer][:parser_fields].delete(:file)
181
+ @importer = Importer.find(params[:importer_id])
182
+ if file.present?
183
+ @importer[:parser_fields]['partial_import_file_path'] = @importer.parser.write_partial_import_file(file)
184
+ @importer.save
185
+ Bulkrax::ImporterJob.perform_later(@importer.id, true)
186
+ redirect_to importer_path(@importer), notice: 'Corrected entries uploaded successfully.'
187
+ else
188
+ redirect_to importer_upload_corrected_entries_path(@importer), alert: 'Importer failed to update with new file.'
189
+ end
190
+ end
191
+
192
+ def external_sets
193
+ if list_external_sets
194
+ render json: { base_url: params[:base_url], sets: @sets }
195
+ else
196
+ render json: { base_url: params[:base_url], error: "unable to pull data from #{params[:base_url]}" }
197
+ end
198
+ end
199
+
200
+ # GET /importers/1/export_errors
201
+ def export_errors
202
+ @importer = Importer.find(params[:importer_id])
203
+ @importer.write_errored_entries_file
204
+ send_content
205
+ end
206
+
207
+ private
208
+
209
+ def files_for_import(file, cloud_files)
210
+ return if file.blank? && cloud_files.blank?
211
+ @importer[:parser_fields]['import_file_path'] = @importer.parser.write_import_file(file) if file.present?
212
+ if cloud_files.present?
213
+ # For BagIt, there will only be one bag, so we get the file_path back and set import_file_path
214
+ # For CSV, we expect only file uploads, so we won't get the file_path back
215
+ # and we expect the import_file_path to be set already
216
+ target = @importer.parser.retrieve_cloud_files(cloud_files)
217
+ @importer[:parser_fields]['import_file_path'] = target if target.present?
218
+ end
219
+ @importer.save
220
+ end
221
+
222
+ # Use callbacks to share common setup or constraints between actions.
223
+ def set_importer
224
+ @importer = Importer.find(params[:id])
225
+ end
226
+
227
+ def importable_params
228
+ params.except(:selected_files)
229
+ end
230
+
231
+ def importable_parser_fields
232
+ params&.[](:importer)&.[](:parser_fields)&.except(:file)&.keys
233
+ end
234
+
235
+ # Only allow a trusted parameters through.
236
+ def importer_params
237
+ importable_params.require(:importer).permit(
238
+ :name,
239
+ :admin_set_id,
240
+ :user_id,
241
+ :frequency,
242
+ :parser_klass,
243
+ :limit,
244
+ :validate_only,
245
+ selected_files: {},
246
+ field_mapping: {},
247
+ parser_fields: [importable_parser_fields]
248
+ )
249
+ end
250
+
251
+ def list_external_sets
252
+ url = params[:base_url] || (@harvester ? @harvester.base_url : nil)
253
+ setup_client(url) if url.present?
254
+
255
+ @sets = [['All', 'all']]
256
+
257
+ begin
258
+ @client.list_sets.each do |s|
259
+ @sets << [s.name, s.spec]
260
+ end
261
+ rescue
262
+ return false
263
+ end
264
+
265
+ @sets
266
+ end
267
+
268
+ def file_param
269
+ params.require(:importer).require(:parser_fields).fetch(:file) if params&.[](:importer)&.[](:parser_fields)&.[](:file)
270
+ end
271
+
272
+ def cloud_params
273
+ params.permit(selected_files: {}).fetch(:selected_files).to_h if params&.[](:selected_files)
274
+ end
275
+
276
+ # Add the field_mapping from the Bulkrax configuration
277
+ def field_mapping_params
278
+ # @todo replace/append once mapping GUI is in place
279
+ field_mapping_key = Bulkrax.parsers.map { |m| m[:class_name] if m[:class_name] == params[:importer][:parser_klass] }.compact.first
280
+ @importer.field_mapping = Bulkrax.field_mappings[field_mapping_key] if field_mapping_key
281
+ end
282
+
283
+ def add_importer_breadcrumbs
284
+ add_breadcrumb t(:'hyrax.controls.home'), main_app.root_path
285
+ add_breadcrumb t(:'hyrax.dashboard.breadcrumbs.admin'), hyrax.dashboard_path
286
+ add_breadcrumb 'Importers', bulkrax.importers_path
287
+ end
288
+
289
+ def setup_client(url)
290
+ return false if url.nil?
291
+ headers = { from: Bulkrax.server_name }
292
+ @client ||= OAI::Client.new(url, headers: headers, parser: 'libxml', metadata_prefix: 'oai_dc')
293
+ end
294
+
295
+ # Download methods
296
+
297
+ def file_path
298
+ @importer.errored_entries_csv_path
299
+ end
300
+
301
+ def download_content_type
302
+ 'text/csv'
303
+ end
304
+
305
+ def render_request(message, validate_only = false)
306
+ if api_request?
307
+ json_response('create', :created, message)
308
+ else
309
+ path = validate_only ? importer_path(@importer) : importers_path
310
+ redirect_to path, notice: message
311
+ end
312
+ end
313
+ end
314
+ # rubocop:enable Metrics/ClassLength
315
+ end