bulkrax 6.0.1 → 8.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +7 -7
  3. data/app/assets/javascripts/bulkrax/bulkrax.js +11 -0
  4. data/app/assets/javascripts/bulkrax/datatables.js +139 -0
  5. data/app/assets/javascripts/bulkrax/exporters.js +4 -4
  6. data/app/assets/javascripts/bulkrax/importers.js.erb +15 -1
  7. data/app/assets/stylesheets/bulkrax/import_export.scss +6 -1
  8. data/app/controllers/bulkrax/entries_controller.rb +52 -3
  9. data/app/controllers/bulkrax/exporters_controller.rb +20 -8
  10. data/app/controllers/bulkrax/importers_controller.rb +31 -12
  11. data/app/controllers/concerns/bulkrax/datatables_behavior.rb +201 -0
  12. data/app/factories/bulkrax/object_factory.rb +135 -163
  13. data/app/factories/bulkrax/object_factory_interface.rb +491 -0
  14. data/app/factories/bulkrax/valkyrie_object_factory.rb +402 -0
  15. data/app/helpers/bulkrax/application_helper.rb +7 -3
  16. data/app/helpers/bulkrax/importers_helper.rb +1 -1
  17. data/app/helpers/bulkrax/validation_helper.rb +4 -4
  18. data/app/jobs/bulkrax/create_relationships_job.rb +28 -17
  19. data/app/jobs/bulkrax/delete_and_import_collection_job.rb +8 -0
  20. data/app/jobs/bulkrax/delete_and_import_file_set_job.rb +8 -0
  21. data/app/jobs/bulkrax/delete_and_import_job.rb +20 -0
  22. data/app/jobs/bulkrax/delete_and_import_work_job.rb +8 -0
  23. data/app/jobs/bulkrax/delete_job.rb +8 -3
  24. data/app/jobs/bulkrax/download_cloud_file_job.rb +17 -4
  25. data/app/jobs/bulkrax/import_collection_job.rb +1 -1
  26. data/app/jobs/bulkrax/import_file_set_job.rb +6 -3
  27. data/app/jobs/bulkrax/import_job.rb +7 -0
  28. data/app/jobs/bulkrax/import_work_job.rb +1 -1
  29. data/app/jobs/bulkrax/importer_job.rb +19 -3
  30. data/app/matchers/bulkrax/application_matcher.rb +0 -2
  31. data/app/models/bulkrax/csv_collection_entry.rb +1 -3
  32. data/app/models/bulkrax/csv_entry.rb +9 -7
  33. data/app/models/bulkrax/entry.rb +9 -11
  34. data/app/models/bulkrax/exporter.rb +11 -4
  35. data/app/models/bulkrax/importer.rb +49 -10
  36. data/app/models/bulkrax/oai_entry.rb +0 -3
  37. data/app/models/bulkrax/oai_set_entry.rb +1 -3
  38. data/app/models/bulkrax/rdf_collection_entry.rb +1 -4
  39. data/app/models/bulkrax/rdf_entry.rb +70 -69
  40. data/app/models/bulkrax/status.rb +10 -1
  41. data/app/models/bulkrax/xml_entry.rb +0 -1
  42. data/app/models/concerns/bulkrax/dynamic_record_lookup.rb +2 -19
  43. data/app/models/concerns/bulkrax/export_behavior.rb +2 -2
  44. data/app/models/concerns/bulkrax/file_factory.rb +174 -118
  45. data/app/models/concerns/bulkrax/file_set_entry_behavior.rb +5 -3
  46. data/app/models/concerns/bulkrax/has_matchers.rb +28 -25
  47. data/app/models/concerns/bulkrax/import_behavior.rb +14 -33
  48. data/app/models/concerns/bulkrax/importer_exporter_behavior.rb +3 -2
  49. data/app/models/concerns/bulkrax/status_info.rb +8 -0
  50. data/app/parsers/bulkrax/application_parser.rb +116 -21
  51. data/app/parsers/bulkrax/bagit_parser.rb +173 -195
  52. data/app/parsers/bulkrax/csv_parser.rb +15 -57
  53. data/app/parsers/bulkrax/oai_dc_parser.rb +44 -16
  54. data/app/parsers/bulkrax/parser_export_record_set.rb +20 -24
  55. data/app/parsers/bulkrax/xml_parser.rb +18 -23
  56. data/app/services/bulkrax/factory_class_finder.rb +92 -0
  57. data/app/services/bulkrax/remove_relationships_for_importer.rb +3 -1
  58. data/app/services/hyrax/custom_queries/find_by_source_identifier.rb +50 -0
  59. data/app/services/wings/custom_queries/find_by_source_identifier.rb +32 -0
  60. data/app/views/bulkrax/entries/_parsed_metadata.html.erb +2 -2
  61. data/app/views/bulkrax/entries/_raw_metadata.html.erb +2 -2
  62. data/app/views/bulkrax/entries/show.html.erb +9 -8
  63. data/app/views/bulkrax/exporters/_form.html.erb +10 -10
  64. data/app/views/bulkrax/exporters/edit.html.erb +1 -1
  65. data/app/views/bulkrax/exporters/index.html.erb +13 -57
  66. data/app/views/bulkrax/exporters/new.html.erb +1 -1
  67. data/app/views/bulkrax/exporters/show.html.erb +6 -12
  68. data/app/views/bulkrax/importers/_browse_everything.html.erb +2 -2
  69. data/app/views/bulkrax/importers/_csv_fields.html.erb +8 -2
  70. data/app/views/bulkrax/importers/_edit_form_buttons.html.erb +8 -1
  71. data/app/views/bulkrax/importers/_edit_item_buttons.html.erb +18 -0
  72. data/app/views/bulkrax/importers/edit.html.erb +1 -1
  73. data/app/views/bulkrax/importers/index.html.erb +20 -64
  74. data/app/views/bulkrax/importers/new.html.erb +1 -1
  75. data/app/views/bulkrax/importers/show.html.erb +8 -14
  76. data/app/views/bulkrax/importers/upload_corrected_entries.html.erb +2 -2
  77. data/app/views/bulkrax/shared/_bulkrax_errors.html.erb +1 -1
  78. data/app/views/bulkrax/shared/_bulkrax_field_mapping.html.erb +1 -1
  79. data/app/views/bulkrax/shared/_entries_tab.html.erb +16 -0
  80. data/config/locales/bulkrax.en.yml +7 -0
  81. data/config/routes.rb +8 -2
  82. data/db/migrate/20230608153601_add_indices_to_bulkrax.rb +20 -9
  83. data/db/migrate/20240208005801_denormalize_status_message.rb +7 -0
  84. data/db/migrate/20240209070952_update_identifier_index.rb +6 -0
  85. data/db/migrate/20240307053156_add_index_to_metadata_bulkrax_identifier.rb +18 -0
  86. data/lib/bulkrax/engine.rb +23 -0
  87. data/lib/bulkrax/version.rb +1 -1
  88. data/lib/bulkrax.rb +107 -19
  89. data/lib/generators/bulkrax/templates/config/initializers/bulkrax.rb +2 -0
  90. data/lib/tasks/bulkrax_tasks.rake +13 -0
  91. data/lib/tasks/reset.rake +4 -4
  92. metadata +64 -8
  93. data/app/views/bulkrax/shared/_collection_entries_tab.html.erb +0 -39
  94. data/app/views/bulkrax/shared/_file_set_entries_tab.html.erb +0 -39
  95. data/app/views/bulkrax/shared/_work_entries_tab.html.erb +0 -39
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d9892c080d7d1cfa595d1965fae2e1b7372f6ec0b7042b0acc7ceb86a0421abd
4
- data.tar.gz: bdd80bd311e47ad4705ed9d2770e24b10248656fa3f78c287943e829ed891c79
3
+ metadata.gz: 6ca767b1e461d5830774bb4d7c49eade799d14298625bdbdccdcbdc0ac997f88
4
+ data.tar.gz: b5024ea772132123fcb922fbe183d22950428ea50b7a8b4152c6bd781b94510f
5
5
  SHA512:
6
- metadata.gz: 0034564d49de171a95cc1b415b9593cb70080102eb4e66cf083eb1e8b2f04e7dce9fd80aef158008ddd17ee88a8e31afec468ce8a2b323d55399fbcabf3c2402
7
- data.tar.gz: 861e1573df358bb3b610fde019c884c1f9ef944956aeabb7cd17c729c6b0ec281fb60036f29ccae3d98fe0aec5f46eed358a8ad87996b599c0c5f71e3366a491
6
+ metadata.gz: 91004f88a97054107a3bbbcbe7f3b3dd84226a286df47992c13bfc5fb483c3bfd4aaa9190e08e567258e5105a317a37bba58fa7857ee6c534153ba930b608ad7
7
+ data.tar.gz: 89a32c155c3931e486b2d41215942b291eb724c59833a031fdc4815a72d26a2df13b015c1b1e2c0dafd608e58ec481a574e20da7bcf95ed76b3e45c3d5f19287
data/Rakefile CHANGED
@@ -25,18 +25,18 @@ require 'bundler/gem_tasks'
25
25
 
26
26
  require 'solr_wrapper/rake_task' unless Rails.env.production?
27
27
 
28
+ require 'rubocop/rake_task'
29
+
30
+ RuboCop::RakeTask.new(:rubocop) do |t|
31
+ t.options = ['--display-cop-names', '--ignore-parent-exclusion', '-a']
32
+ end
33
+
28
34
  begin
29
35
  require 'rspec/core/rake_task'
30
36
 
31
37
  RSpec::Core::RakeTask.new(:spec)
32
38
 
33
- task default: :spec
39
+ task default: [:rubocop, :spec]
34
40
  rescue LoadError # rubocop:disable Lint/HandleExceptions
35
41
  # no rspec available
36
42
  end
37
-
38
- require 'rubocop/rake_task'
39
-
40
- RuboCop::RakeTask.new(:rubocop) do |t|
41
- t.options = ['--display-cop-names']
42
- end
@@ -8,4 +8,15 @@ $(document).on('turbolinks:load ready', function() {
8
8
  $('button#fm_toggle').click(function() {
9
9
  $('#field_mapping').toggle();
10
10
  });
11
+ $('#bulkraxItemModal').on('show.bs.modal', function (event) {
12
+ var button = $(event.relatedTarget) // Button that triggered the modal
13
+ var recipient = button.data('entry-id') // Extract info from data-* attributes
14
+ // If necessary, you could initiate an AJAX request here (and then do the updating in a callback).
15
+ // Update the modal's content. We'll use jQuery here, but you could use a data binding library or other methods instead.
16
+ var modal = $(this)
17
+ modal.find('a').each(function() {
18
+ this.href = this.href.replace(/\d+\?/, recipient + '?')
19
+ })
20
+ return true
21
+ })
11
22
  });
@@ -0,0 +1,139 @@
1
+ Blacklight.onLoad(function() {
2
+ if($('#importer-show-table').length) {
3
+ $('#importer-show-table').DataTable( {
4
+ 'processing': true,
5
+ 'serverSide': true,
6
+ "ajax": window.location.href.replace(/(\/(importers|exporters)\/\d+)/, "$1/entry_table.json"),
7
+ "pageLength": 30,
8
+ "lengthMenu": [[30, 100, 200], [30, 100, 200]],
9
+ "columns": [
10
+ { "data": "identifier" },
11
+ { "data": "id" },
12
+ { "data": "status_message" },
13
+ { "data": "type" },
14
+ { "data": "updated_at" },
15
+ { "data": "errors", "orderable": false },
16
+ { "data": "actions", "orderable": false }
17
+ ],
18
+ initComplete: function () {
19
+ // Add entry class filter
20
+ entrySelect.bind(this)()
21
+ // Add status filter
22
+ statusSelect.bind(this)()
23
+ // Add refresh link
24
+ refreshLink.bind(this)()
25
+ }
26
+ } );
27
+ }
28
+
29
+ if($('#importers-table').length) {
30
+ $('#importers-table').DataTable( {
31
+ 'processing': true,
32
+ 'serverSide': true,
33
+ "ajax": window.location.href.replace(/(\/importers)/, "$1/importer_table.json"),
34
+ "pageLength": 30,
35
+ "lengthMenu": [[30, 100, 200], [30, 100, 200]],
36
+ "columns": [
37
+ { "data": "name" },
38
+ { "data": "status_message" },
39
+ { "data": "last_imported_at" },
40
+ { "data": "next_import_at" },
41
+ { "data": "enqueued_records", "orderable": false },
42
+ { "data": "processed_records", "orderable": false },
43
+ { "data": "failed_records", "orderable": false },
44
+ { "data": "deleted_records", "orderable": false },
45
+ { "data": "total_collection_entries", "orderable": false },
46
+ { "data": "total_work_entries", "orderable": false },
47
+ { "data": "total_file_set_entries", "orderable": false },
48
+ { "data": "actions", "orderable": false }
49
+ ],
50
+ initComplete: function () {
51
+ // Add status filter
52
+ statusSelect.bind(this)()
53
+ // Add refresh link
54
+ refreshLink.bind(this)()
55
+ }
56
+ } );
57
+ }
58
+
59
+ if($('#exporters-table').length) {
60
+ $('#exporters-table').DataTable( {
61
+ 'processing': true,
62
+ 'serverSide': true,
63
+ "ajax": window.location.href.replace(/(\/exporters)/, "$1/exporter_table.json"),
64
+ "pageLength": 30,
65
+ "lengthMenu": [[30, 100, 200], [30, 100, 200]],
66
+ "columns": [
67
+ { "data": "name" },
68
+ { "data": "status_message" },
69
+ { "data": "created_at" },
70
+ { "data": "download" },
71
+ { "data": "actions", "orderable": false }
72
+ ],
73
+ initComplete: function () {
74
+ // Add status filter
75
+ statusSelect.bind(this)()
76
+ // Add refresh link
77
+ refreshLink.bind(this)()
78
+ }
79
+ } );
80
+ }
81
+
82
+ })
83
+
84
+ function entrySelect() {
85
+ let entrySelect = document.createElement('select')
86
+ entrySelect.id = 'entry-filter'
87
+ entrySelect.classList.value = 'form-control input-sm'
88
+ entrySelect.style.marginRight = '10px'
89
+
90
+ entrySelect.add(new Option('Filter by Entry Class', ''))
91
+ // Read the options from the footer and add them to the entrySelect
92
+ $('#importer-entry-classes').text().split('|').forEach(function (col, i) {
93
+ entrySelect.add(new Option(col.trim()))
94
+ })
95
+ document.querySelector('div#importer-show-table_filter').firstChild.prepend(entrySelect)
96
+
97
+ // Apply listener for user change in value
98
+ entrySelect.addEventListener('change', function () {
99
+ var val = entrySelect.value;
100
+ this.api()
101
+ .search(val ? val : '', false, false)
102
+ .draw();
103
+ }.bind(this));
104
+ }
105
+
106
+ function statusSelect() {
107
+ let statusSelect = document.createElement('select');
108
+ statusSelect.id = 'status-filter'
109
+ statusSelect.classList.value = 'form-control input-sm'
110
+ statusSelect.style.marginRight = '10px'
111
+
112
+ statusSelect.add(new Option('Filter by Status', ''));
113
+ statusSelect.add(new Option('Complete'))
114
+ statusSelect.add(new Option('Pending'))
115
+ statusSelect.add(new Option('Failed'))
116
+ statusSelect.add(new Option('Skipped'))
117
+ statusSelect.add(new Option('Deleted'))
118
+ statusSelect.add(new Option('Complete (with failures)'))
119
+
120
+ document.querySelector('div.dataTables_filter').firstChild.prepend(statusSelect)
121
+
122
+ // Apply listener for user change in value
123
+ statusSelect.addEventListener('change', function () {
124
+ var val = statusSelect.value;
125
+ this.api()
126
+ .search(val ? val : '', false, false)
127
+ .draw();
128
+ }.bind(this));
129
+ }
130
+
131
+ function refreshLink() {
132
+ let refreshLink = document.createElement('a');
133
+ refreshLink.onclick = function() {
134
+ this.api().ajax.reload(null, false)
135
+ }.bind(this)
136
+ refreshLink.classList.value = 'fa fa-refresh'
137
+ refreshLink.style.marginLeft = '10px'
138
+ document.querySelector('div.dataTables_filter').firstChild.append(refreshLink)
139
+ }
@@ -26,14 +26,14 @@ function removeRequired(allSources) {
26
26
 
27
27
  // hide all export_source
28
28
  function hide(allSources) {
29
- allSources.addClass('d-none');
30
- allSources.find('#exporter_export_source').addClass('.d-none').attr('type', 'd-none');
29
+ allSources.addClass('d-none hidden');
30
+ allSources.find('#exporter_export_source').addClass('.d-none hidden').attr('type', 'd-none hidden');
31
31
  }
32
32
 
33
33
  // unhide selected export_source
34
34
  function unhideSelected(selectedSource) {
35
- selectedSource.removeClass('d-none').removeAttr('type');
36
- selectedSource.parent().removeClass('d-none').removeAttr('type');
35
+ selectedSource.removeClass('d-none hidden').removeAttr('type');
36
+ selectedSource.parent().removeClass('d-none hidden').removeAttr('type');
37
37
  };
38
38
 
39
39
  // add the autocomplete javascript
@@ -74,12 +74,14 @@ function handleFileToggle(file_path) {
74
74
  $('#file_path').hide()
75
75
  $('#file_upload').hide()
76
76
  $('#cloud').hide()
77
+ $('#existing_options').hide()
77
78
  $('#file_path input').attr('required', null)
78
79
  $('#file_upload input').attr('required', null)
79
80
  } else {
80
81
  $('#file_path').show()
81
82
  $('#file_upload').hide()
82
83
  $('#cloud').hide()
84
+ $('#existing_options').hide()
83
85
  $('#file_path input').attr('required', 'required')
84
86
  $('#file_upload input').attr('required', null)
85
87
  $('#importer_parser_fields_file_style_specify_a_path_on_the_server').attr('checked', true)
@@ -89,6 +91,7 @@ function handleFileToggle(file_path) {
89
91
  $('#file_path').hide()
90
92
  $('#file_upload').show()
91
93
  $('#cloud').hide()
94
+ $('#existing_options').hide()
92
95
  $('#file_path input').attr('required', null)
93
96
  $('#file_upload input').attr('required', 'required')
94
97
  })
@@ -96,6 +99,7 @@ function handleFileToggle(file_path) {
96
99
  $('#file_path').show()
97
100
  $('#file_upload').hide()
98
101
  $('#cloud').hide()
102
+ $('#existing_options').hide()
99
103
  $('#file_path input').attr('required', 'required')
100
104
  $('#file_upload input').attr('required', null)
101
105
  })
@@ -103,9 +107,19 @@ function handleFileToggle(file_path) {
103
107
  $('#file_path').hide()
104
108
  $('#file_upload').hide()
105
109
  $('#cloud').show()
110
+ $('#existing_options').hide()
106
111
  $('#file_path input').attr('required', null)
107
112
  $('#file_upload input').attr('required', null)
108
113
  })
114
+ $('#importer_parser_fields_file_style_existing_entries').click(function(e){
115
+ $('#file_path').hide()
116
+ $('#file_upload').hide()
117
+ $('#cloud').hide()
118
+ $('#existing_options').show()
119
+ $('#file_path input').attr('required', null)
120
+ $('#file_upload input').attr('required', null)
121
+ })
122
+
109
123
  }
110
124
 
111
125
  function handleParserKlass() {
@@ -189,4 +203,4 @@ function setError(selector, error) {
189
203
  selector.attr('disabled', true)
190
204
  }
191
205
 
192
- $(document).on({'ready': prepBulkrax, 'turbolinks:load': prepBulkrax})
206
+ $(document).on({'ready': prepBulkrax, 'turbolinks:load': prepBulkrax})
@@ -34,4 +34,9 @@ div#s2id_exporter_export_source_collection {
34
34
 
35
35
  .bulkrax-clear-toggles {
36
36
  clear: both;
37
- }
37
+ }
38
+
39
+ #existing_options .collection_check_boxes {
40
+ margin-left: 10px;
41
+ margin-right: 10px;
42
+ }
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_dependency "bulkrax/application_controller"
4
- require_dependency "oai"
5
-
6
3
  module Bulkrax
7
4
  class EntriesController < ApplicationController
8
5
  include Hyrax::ThemedLayoutController if defined?(::Hyrax)
@@ -18,6 +15,58 @@ module Bulkrax
18
15
  end
19
16
  end
20
17
 
18
+ def update
19
+ @entry = Entry.find(params[:id])
20
+ type = case @entry.type.downcase
21
+ when /fileset/
22
+ 'file_set'
23
+ when /collection/
24
+ 'collection'
25
+ else
26
+ 'work'
27
+ end
28
+ item = @entry.importerexporter
29
+ # do not run counters as it loads the whole parser
30
+ current_run = item.current_run(skip_counts: true)
31
+ @entry.set_status_info('Pending', current_run)
32
+ ScheduleRelationshipsJob.set(wait: 5.minutes).perform_later(importer_id: @entry.importer.id)
33
+
34
+ if params[:destroy_first]
35
+ "Bulkrax::DeleteAndImport#{type.camelize}Job".constantize.perform_later(@entry, current_run)
36
+ else
37
+ "Bulkrax::Import#{type.camelize}Job".constantize.perform_later(@entry.id, current_run.id)
38
+ end
39
+
40
+ entry_path = item.class.to_s.include?('Importer') ? bulkrax.importer_entry_path(item.id, @entry.id) : bulkrax.exporter_entry_path(item.id, @entry.id)
41
+
42
+ redirect_back fallback_location: entry_path, notice: "Entry #{@entry.id} update has been queued"
43
+ end
44
+
45
+ def destroy
46
+ @entry = Entry.find(params[:id])
47
+ @status = ""
48
+ begin
49
+ work = @entry.factory&.find
50
+ if work.present?
51
+ work.destroy
52
+ @entry.destroy
53
+ @status = "Entry and work deleted"
54
+ else
55
+ @entry.destroy
56
+ @status = "Entry deleted"
57
+ end
58
+ rescue StandardError => e
59
+ @status = "Error: #{e.message}"
60
+ end
61
+
62
+ item = @entry.importerexporter
63
+ entry_path = item.class.to_s.include?('Importer') ? bulkrax.importer_entry_path(item.id, @entry.id) : bulkrax.exporter_entry_path(item.id, @entry.id)
64
+
65
+ redirect_back fallback_location: entry_path, notice: @status
66
+ end
67
+
68
+ protected
69
+
21
70
  # GET /importers/1/entries/1
22
71
  def show_importer
23
72
  @importer = Importer.find(params[:importer_id])
@@ -1,14 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_dependency "bulkrax/application_controller"
4
-
5
3
  module Bulkrax
6
4
  class ExportersController < ApplicationController
7
5
  include Hyrax::ThemedLayoutController if defined?(::Hyrax)
8
6
  include Bulkrax::DownloadBehavior
7
+ include Bulkrax::DatatablesBehavior
9
8
  before_action :authenticate_user!
10
9
  before_action :check_permissions
11
- before_action :set_exporter, only: [:show, :edit, :update, :destroy]
10
+ before_action :set_exporter, only: [:show, :entry_table, :edit, :update, :destroy]
12
11
  with_themed_layout 'dashboard' if defined?(::Hyrax)
13
12
 
14
13
  # GET /exporters
@@ -19,16 +18,29 @@ module Bulkrax
19
18
  add_exporter_breadcrumbs if defined?(::Hyrax)
20
19
  end
21
20
 
21
+ def exporter_table
22
+ @exporters = Exporter.order(table_order).page(table_page).per(table_per_page)
23
+ @exporters = @exporters.where(exporter_table_search) if exporter_table_search.present?
24
+ respond_to do |format|
25
+ format.json { render json: format_exporters(@exporters) }
26
+ end
27
+ end
28
+
22
29
  # GET /exporters/1
23
30
  def show
24
31
  if defined?(::Hyrax)
25
32
  add_exporter_breadcrumbs
26
33
  add_breadcrumb @exporter.name
27
34
  end
35
+ @first_entry = @exporter.entries.first
36
+ end
28
37
 
29
- @work_entries = @exporter.entries.where(type: @exporter.parser.entry_class.to_s).page(params[:work_entries_page]).per(30)
30
- @collection_entries = @exporter.entries.where(type: @exporter.parser.collection_entry_class.to_s).page(params[:collections_entries_page]).per(30)
31
- @file_set_entries = @exporter.entries.where(type: @exporter.parser.file_set_entry_class.to_s).page(params[:file_set_entries_page]).per(30)
38
+ def entry_table
39
+ @entries = @exporter.entries.order(table_order).page(table_page).per(table_per_page)
40
+ @entries = @entries.where(entry_table_search) if entry_table_search.present?
41
+ respond_to do |format|
42
+ format.json { render json: format_entries(@entries, @exporter) }
43
+ end
32
44
  end
33
45
 
34
46
  # GET /exporters/new
@@ -48,7 +60,7 @@ module Bulkrax
48
60
  end
49
61
 
50
62
  # Correctly populate export_source_collection input
51
- @collection = Collection.find(@exporter.export_source) if @exporter.export_source.present? && @exporter.export_from == 'collection'
63
+ @collection = Bulkrax.object_factory.find(@exporter.export_source) if @exporter.export_source.present? && @exporter.export_from == 'collection'
52
64
  end
53
65
 
54
66
  # POST /exporters
@@ -102,7 +114,7 @@ module Bulkrax
102
114
 
103
115
  # Use callbacks to share common setup or constraints between actions.
104
116
  def set_exporter
105
- @exporter = Exporter.find(params[:id])
117
+ @exporter = Exporter.find(params[:id] || params[:exporter_id])
106
118
  end
107
119
 
108
120
  # Only allow a trusted parameters through.
@@ -1,34 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_dependency 'bulkrax/application_controller'
4
- require_dependency 'oai'
5
-
6
3
  module Bulkrax
7
4
  # rubocop:disable Metrics/ClassLength
8
- class ImportersController < ApplicationController
5
+ class ImportersController < ::Bulkrax::ApplicationController
9
6
  include Hyrax::ThemedLayoutController if defined?(::Hyrax)
10
7
  include Bulkrax::DownloadBehavior
11
8
  include Bulkrax::API
9
+ include Bulkrax::DatatablesBehavior
12
10
  include Bulkrax::ValidationHelper
13
11
 
14
12
  protect_from_forgery unless: -> { api_request? }
15
13
  before_action :token_authenticate!, if: -> { api_request? }, only: [:create, :update, :delete]
16
14
  before_action :authenticate_user!, unless: -> { api_request? }
17
15
  before_action :check_permissions
18
- before_action :set_importer, only: [:show, :edit, :update, :destroy]
16
+ before_action :set_importer, only: [:show, :entry_table, :edit, :update, :destroy]
19
17
  with_themed_layout 'dashboard' if defined?(::Hyrax)
20
18
 
21
19
  # GET /importers
22
20
  def index
23
21
  # NOTE: We're paginating this in the browser.
24
- @importers = Importer.order(created_at: :desc).all
25
22
  if api_request?
23
+ @importers = Importer.order(created_at: :desc).all
26
24
  json_response('index')
27
25
  elsif defined?(::Hyrax)
28
26
  add_importer_breadcrumbs
29
27
  end
30
28
  end
31
29
 
30
+ def importer_table
31
+ @importers = Importer.order(table_order).page(table_page).per(table_per_page)
32
+ @importers = @importers.where(importer_table_search) if importer_table_search.present?
33
+ respond_to do |format|
34
+ format.json { render json: format_importers(@importers) }
35
+ end
36
+ end
37
+
32
38
  # GET /importers/1
33
39
  def show
34
40
  if api_request?
@@ -37,9 +43,15 @@ module Bulkrax
37
43
  add_importer_breadcrumbs
38
44
  add_breadcrumb @importer.name
39
45
  end
40
- @work_entries = @importer.entries.where(type: @importer.parser.entry_class.to_s).page(params[:work_entries_page]).per(30)
41
- @collection_entries = @importer.entries.where(type: @importer.parser.collection_entry_class.to_s).page(params[:collections_entries_page]).per(30)
42
- @file_set_entries = @importer.entries.where(type: @importer.parser.file_set_entry_class.to_s).page(params[:file_set_entries_page]).per(30)
46
+ @first_entry = @importer.entries.first
47
+ end
48
+
49
+ def entry_table
50
+ @entries = @importer.entries.order(table_order).page(table_page).per(table_per_page)
51
+ @entries = @entries.where(entry_table_search) if entry_table_search.present?
52
+ respond_to do |format|
53
+ format.json { render json: format_entries(@entries, @importer) }
54
+ end
43
55
  end
44
56
 
45
57
  # GET /importers/new
@@ -202,10 +214,11 @@ module Bulkrax
202
214
  return if file.blank? && cloud_files.blank?
203
215
  @importer[:parser_fields]['import_file_path'] = @importer.parser.write_import_file(file) if file.present?
204
216
  if cloud_files.present?
217
+ @importer[:parser_fields]['cloud_file_paths'] = cloud_files
205
218
  # For BagIt, there will only be one bag, so we get the file_path back and set import_file_path
206
219
  # For CSV, we expect only file uploads, so we won't get the file_path back
207
220
  # and we expect the import_file_path to be set already
208
- target = @importer.parser.retrieve_cloud_files(cloud_files)
221
+ target = @importer.parser.retrieve_cloud_files(cloud_files, @importer)
209
222
  @importer[:parser_fields]['import_file_path'] = target if target.present?
210
223
  end
211
224
  @importer.save
@@ -213,7 +226,7 @@ module Bulkrax
213
226
 
214
227
  # Use callbacks to share common setup or constraints between actions.
215
228
  def set_importer
216
- @importer = Importer.find(params[:id])
229
+ @importer = Importer.find(params[:id] || params[:importer_id])
217
230
  end
218
231
 
219
232
  def importable_params
@@ -221,7 +234,7 @@ module Bulkrax
221
234
  end
222
235
 
223
236
  def importable_parser_fields
224
- params&.[](:importer)&.[](:parser_fields)&.except(:file)&.keys
237
+ params&.[](:importer)&.[](:parser_fields)&.except(:file, :entry_statuses)&.keys&. + [{ "entry_statuses" => [] }]
225
238
  end
226
239
 
227
240
  # Only allow a trusted parameters through.
@@ -310,10 +323,16 @@ module Bulkrax
310
323
  end
311
324
 
312
325
  def set_files_parser_fields
326
+ @importer.parser_fields['update_files'] =
327
+ @importer.parser_fields['replace_files'] =
328
+ @importer.parser_fields['remove_and_rerun'] =
329
+ @importer.parser_fields['metadata_only'] = false
313
330
  if params[:commit] == 'Update Metadata and Files'
314
331
  @importer.parser_fields['update_files'] = true
315
332
  elsif params[:commit] == ('Update and Replace Files' || 'Update and Re-Harvest All Items')
316
333
  @importer.parser_fields['replace_files'] = true
334
+ elsif params[:commit] == 'Remove and Rerun'
335
+ @importer.parser_fields['remove_and_rerun'] = true
317
336
  elsif params[:commit] == 'Update and Harvest Updated Items'
318
337
  return
319
338
  else