bulkrax 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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