bulkrax 8.2.0 → 8.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7886fb5eefc500cc8e567d9097e6930e67cee2908fa7fa0d79ce05fc714db392
4
- data.tar.gz: c6e720816dd152931df91e06be37977216a7ef06875a98386350706e4df1e3ea
3
+ metadata.gz: 9a409c17f35bc09ef0a8c63d06a064d01fbff68a0e4c0b91c9bfaed45d6e8169
4
+ data.tar.gz: 7fad94124795ff133b83d05030c550f2a52f808ac017fdd3a436c17ce039cd01
5
5
  SHA512:
6
- metadata.gz: 62971f4eab58de239643d016ec8f8701b6e71953bbb8ccc4bf1d74fd8a88d3798c506004704203107e6f676218bc0dcd337776ecccc423b6c932aeddcd0dacf5
7
- data.tar.gz: f3710a5e394a470753ea83d5e007505afd91a8fcdc3c383465fdaa7f2eb9c0901b3bef7cb69ae2c9bfa6d508231095e44ac7781cc9c52565162adfe2e58a5c3d
6
+ metadata.gz: 65280762e81baa620e73d965d5e7c58ec4ccb40d303c00cf634e7f9b3b3850e541cc9964900ce7b9aec9f6be1a7fe81dd9781db5b74209a9f8661f5f8a96f595
7
+ data.tar.gz: e91e65f6de8edc1640dd9b6e75c246fff4fd0812a3f87f6b4600dd9c95afc095be6076c9a80c5bca50ccc73c3831fc0a30c1160b46f18c483a6d68277bf762a8
data/README.md CHANGED
@@ -24,6 +24,14 @@ $ rails db:migrate
24
24
 
25
25
  If using Sidekiq, set up queues for `import` and `export`.
26
26
 
27
+ ### Bundle errors on ARM
28
+
29
+ If posix-spawn is failing to bundle on an ARM based processor, try the following
30
+
31
+ `bundle config build.posix-spawn --with-cflags="-Wno-incompatible-function-pointer-types"`
32
+
33
+ Then rebundle. See https://github.com/rtomayko/posix-spawn/issues/92
34
+
27
35
  ### Manual Installation
28
36
 
29
37
  Add this line to your application's Gemfile:
@@ -5,18 +5,20 @@ $(document).on('turbolinks:load ready', function() {
5
5
  $('button#err_toggle').click(function() {
6
6
  $('#error_trace').toggle();
7
7
  });
8
+
8
9
  $('button#fm_toggle').click(function() {
9
10
  $('#field_mapping').toggle();
10
11
  });
12
+
11
13
  $('#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
+ var button = $(event.relatedTarget); // Button that triggered the modal
15
+ var recipient = button.data('entry-id'); // Extract info from data-* attributes
14
16
  // If necessary, you could initiate an AJAX request here (and then do the updating in a callback).
15
17
  // 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)
18
+ var modal = $(this);
17
19
  modal.find('a').each(function() {
18
- this.href = this.href.replace(/\d+\?/, recipient + '?')
19
- })
20
- return true
21
- })
20
+ this.href = this.href.replace(/\d+\?/, recipient + '?');
21
+ });
22
+ return true;
23
+ });
22
24
  });
@@ -2,205 +2,240 @@
2
2
  // All this logic will automatically be available in application.js.
3
3
 
4
4
  function prepBulkrax(event) {
5
- var refresh_button = $('.refresh-set-source')
6
- var base_url = $('#importer_parser_fields_base_url')
7
- var initial_base_url = base_url.val()
8
- var file_path_value = $('#importer_parser_fields_import_file_path').val()
9
- handleFileToggle(file_path_value)
5
+ var refresh_button = $('.refresh-set-source');
6
+ var base_url = $('#importer_parser_fields_base_url');
7
+ var initial_base_url = base_url.val();
8
+ var file_path_value = $('#importer_parser_fields_import_file_path').val();
9
+ handleFileToggle(file_path_value);
10
+
11
+ // Initialize the uploader only if hyraxUploader is defined
12
+ if (typeof $.fn.hyraxUploader === 'function') {
13
+ // Initialize the uploader
14
+ $('.fileupload-bulkrax').hyraxUploader({ maxNumberOfFiles: 1 });
15
+
16
+ // Function to toggle 'required' attribute based on uploaded files
17
+ function toggleRequiredAttribute() {
18
+ const fileInput = $('#addfiles');
19
+ const uploadedFilesTable = $('.fileupload-bulkrax tbody.files');
20
+
21
+ if (uploadedFilesTable.find('tr.template-download').length > 0) {
22
+ // Remove 'required' if there are uploaded files
23
+ fileInput.removeAttr('required');
24
+ } else {
25
+ // Add 'required' if no uploaded files
26
+ fileInput.attr('required', 'required');
27
+ }
28
+ }
29
+
30
+ // Check the required attribute when a file is added or removed
31
+ $('#addfiles').on('change', function() {
32
+ toggleRequiredAttribute();
33
+ });
34
+
35
+ // Also check when an upload completes or is canceled
36
+ $('.fileupload-bulkrax').on('fileuploadcompleted fileuploaddestroyed', function() {
37
+ toggleRequiredAttribute();
38
+ });
39
+
40
+ // Ensure 'required' is only added if there are no files on form reset
41
+ $('#file-upload-cancel-btn').on('click', function() {
42
+ $('#addfiles').attr('required', 'required');
43
+ $('#addfiles').val(''); // Clear file input to ensure 'required' behavior resets
44
+ });
45
+
46
+ // Initial check in case files are already uploaded
47
+ toggleRequiredAttribute();
48
+ }
10
49
 
11
50
  // handle refreshing/loading of external sets via button click
12
51
  $('body').on('click', '.refresh-set-source', function(e) {
13
- e.preventDefault()
52
+ e.preventDefault();
14
53
 
15
- external_set_select = $("#importer_parser_fields_set")
16
- handleSourceLoad(refresh_button, base_url, external_set_select)
17
- })
54
+ external_set_select = $("#importer_parser_fields_set");
55
+ handleSourceLoad(refresh_button, base_url, external_set_select);
56
+ });
18
57
 
19
58
  // handle refreshing/loading of external sets via blur event for the base_url field
20
59
  $('body').on('blur', '#importer_parser_fields_base_url', function(e) {
21
- e.preventDefault()
60
+ e.preventDefault();
22
61
 
23
62
  // retrieve the latest base_url
24
- base_url = $('#importer_parser_fields_base_url')
63
+ base_url = $('#importer_parser_fields_base_url');
25
64
 
26
65
  // ensure we don't make another query if the value is the same -- this can be forced by clicking the refresh button
27
66
  if (initial_base_url != base_url.val()) {
28
- external_set_select = $("#importer_parser_fields_set")
29
- handleSourceLoad(refresh_button, base_url, external_set_select)
30
- initial_base_url = base_url.val()
67
+ external_set_select = $("#importer_parser_fields_set");
68
+ handleSourceLoad(refresh_button, base_url, external_set_select);
69
+ initial_base_url = base_url.val();
31
70
  }
32
- })
71
+ });
33
72
 
34
73
  // hide and show correct parser fields depending on klass setting
35
74
  $('body').on('change', '#importer_parser_klass', function(e) {
36
- handleParserKlass()
37
- })
38
- handleParserKlass()
75
+ handleParserKlass();
76
+ });
77
+ handleParserKlass();
39
78
 
40
79
  // observer for cloud files being added
41
80
  var form = document.getElementById('new_importer');
42
81
  if (form == null) {
43
- var form = document.getElementsByClassName('edit_importer')[0];
82
+ form = document.getElementsByClassName('edit_importer')[0];
44
83
  }
84
+
45
85
  // only setup the observer on the new and edit importer pages
46
86
  if (form != null) {
47
87
  var config = { childList: true, attributes: true };
48
88
  var callback = function(mutationsList) {
49
89
  for(var mutation of mutationsList) {
50
-
51
90
  if (mutation.type == 'childList') {
52
91
  browseButton = document.getElementById('browse');
53
- var exp = /selected_files\[[0-9]*\]\[url\]/
92
+ var exp = /selected_files\[[0-9]*\]\[url\]/;
54
93
  for (var node of mutation.addedNodes) {
55
94
  if (node.attributes != undefined) {
56
- var name = node.attributes.name.value
95
+ var name = node.attributes.name.value;
57
96
  if (exp.test(name)) {
58
97
  browseButton.innerHTML = 'Cloud Files Added';
59
98
  browseButton.style.backgroundColor = 'green';
60
- browseButton.after(document.createElement("br"), node.value.toString())
99
+ browseButton.after(document.createElement("br"), node.value.toString());
61
100
  }
62
101
  }
63
102
  }
64
103
  }
65
104
  }
66
105
  };
67
- var observer = new MutationObserver (callback);
68
- observer.observe (form, config);
106
+ var observer = new MutationObserver(callback);
107
+ observer.observe(form, config);
69
108
  }
70
109
  }
71
110
 
72
111
  function handleFileToggle(file_path) {
73
112
  if (file_path === undefined || file_path.length === 0) {
74
- $('#file_path').hide()
75
- $('#file_upload').hide()
76
- $('#cloud').hide()
77
- $('#existing_options').hide()
78
- $('#file_path input').attr('required', null)
79
- $('#file_upload input').attr('required', null)
113
+ $('#file_path').hide();
114
+ $('#file_upload').hide();
115
+ $('#cloud').hide();
116
+ $('#existing_options').hide();
117
+ $('#file_path input').attr('required', null);
118
+ $('#file_upload input').attr('required', null);
80
119
  } else {
81
- $('#file_path').show()
82
- $('#file_upload').hide()
83
- $('#cloud').hide()
84
- $('#existing_options').hide()
85
- $('#file_path input').attr('required', 'required')
86
- $('#file_upload input').attr('required', null)
87
- $('#importer_parser_fields_file_style_specify_a_path_on_the_server').attr('checked', true)
120
+ $('#file_path').show();
121
+ $('#file_upload').hide();
122
+ $('#cloud').hide();
123
+ $('#existing_options').hide();
124
+ $('#file_path input').attr('required', 'required');
125
+ $('#file_upload input').attr('required', null);
126
+ $('#importer_parser_fields_file_style_specify_a_path_on_the_server').attr('checked', true);
88
127
  }
89
128
 
90
129
  $('#importer_parser_fields_file_style_upload_a_file').click(function(e){
91
- $('#file_path').hide()
92
- $('#file_upload').show()
93
- $('#cloud').hide()
94
- $('#existing_options').hide()
95
- $('#file_path input').attr('required', null)
96
- $('#file_upload input').attr('required', 'required')
97
- })
130
+ $('#file_path').hide();
131
+ $('#file_upload').show();
132
+ $('#cloud').hide();
133
+ $('#existing_options').hide();
134
+ $('#file_path input').attr('required', null);
135
+ $('#file_upload input').attr('required', 'required');
136
+ });
98
137
  $('#importer_parser_fields_file_style_specify_a_path_on_the_server').click(function(e){
99
- $('#file_path').show()
100
- $('#file_upload').hide()
101
- $('#cloud').hide()
102
- $('#existing_options').hide()
103
- $('#file_path input').attr('required', 'required')
104
- $('#file_upload input').attr('required', null)
105
- })
138
+ $('#file_path').show();
139
+ $('#file_upload').hide();
140
+ $('#cloud').hide();
141
+ $('#existing_options').hide();
142
+ $('#file_path input').attr('required', 'required');
143
+ $('#file_upload input').attr('required', null);
144
+ });
106
145
  $('#importer_parser_fields_file_style_add_cloud_file').click(function(e){
107
- $('#file_path').hide()
108
- $('#file_upload').hide()
109
- $('#cloud').show()
110
- $('#existing_options').hide()
111
- $('#file_path input').attr('required', null)
112
- $('#file_upload input').attr('required', null)
113
- })
146
+ $('#file_path').hide();
147
+ $('#file_upload').hide();
148
+ $('#cloud').show();
149
+ $('#existing_options').hide();
150
+ $('#file_path input').attr('required', null);
151
+ $('#file_upload input').attr('required', null);
152
+ });
114
153
  $('#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
-
154
+ $('#file_path').hide();
155
+ $('#file_upload').hide();
156
+ $('#cloud').hide();
157
+ $('#existing_options').show();
158
+ $('#file_path input').attr('required', null);
159
+ $('#file_upload input').attr('required', null);
160
+ });
123
161
  }
124
162
 
125
163
  function handleParserKlass() {
126
164
  <% Bulkrax.parsers.map{ |p| p[:partial]}.uniq.each do |partial| %>
127
165
  if($('.<%= partial %>').length > 0) {
128
- window.<%= partial %> = $('.<%= partial %>').detach()
166
+ window.<%= partial %> = $('.<%= partial %>').detach();
129
167
  }
130
168
  <% end %>
131
169
 
132
- var parser_klass = $("#importer_parser_klass option:selected")
170
+ var parser_klass = $("#importer_parser_klass option:selected");
133
171
  if(parser_klass.length > 0 && parser_klass.data('partial') && parser_klass.data('partial').length > 0) {
134
- $('.parser_fields').append(window[parser_klass.data('partial')])
172
+ $('.parser_fields').append(window[parser_klass.data('partial')]);
135
173
  }
136
174
 
137
- handleBrowseEverything()
138
- var file_path_value = $('#importer_parser_fields_import_file_path').val()
139
- handleFileToggle(file_path_value)
175
+ handleBrowseEverything();
176
+ var file_path_value = $('#importer_parser_fields_import_file_path').val();
177
+ handleFileToggle(file_path_value);
140
178
  }
141
179
 
142
180
  function handleBrowseEverything(){
143
- var button = $("button[data-toggle='browse-everything']")
181
+ var button = $("button[data-toggle='browse-everything']");
144
182
  if(button.length == 0) { return; }
145
183
  button.browseEverything({
146
184
  route: button.data('route'),
147
185
  target: button.data('target')
148
186
  }).done(function(data) {
149
187
  var evt = { isDefaultPrevented: function() { return false; } };
150
- $('.ev-browser.show').removeClass('show')
188
+ $('.ev-browser.show').removeClass('show');
151
189
  if($('#fileupload').length > 0) {
152
- var files = $.map(data, function(d) { return { name: d.file_name, size: d.file_size, id: d.url } });
190
+ var files = $.map(data, function(d) { return { name: d.file_name, size: d.file_size, id: d.url }; });
153
191
  $.blueimp.fileupload.prototype.options.done.call($('#fileupload').fileupload(), evt, { result: { files: files }});
154
192
  }
155
- return true
156
- // User has submitted files; data contains an array of URLs and their options
193
+ return true;
157
194
  }).cancel(function() {
158
- $('.ev-browser.show').removeClass('show')
159
- // User cancelled the browse operation
195
+ $('.ev-browser.show').removeClass('show');
160
196
  }).fail(function(status, error, text) {
161
- $('.ev-browser.show').removeClass('show')
162
- // URL retrieval experienced a technical failure
197
+ $('.ev-browser.show').removeClass('show');
163
198
  });
164
199
  }
165
200
 
166
201
  function handleSourceLoad(refresh_button, base_url, external_set_select) {
167
202
  if (base_url.val() == "") { // ignore empty base_url value
168
- return
203
+ return;
169
204
  }
170
205
 
171
- var initial_button_text = refresh_button.html()
206
+ var initial_button_text = refresh_button.html();
172
207
 
173
- refresh_button.html('Refreshing...')
174
- refresh_button.attr('disabled', true)
208
+ refresh_button.html('Refreshing...');
209
+ refresh_button.attr('disabled', true);
175
210
 
176
211
  $.post('/importers/external_sets', {
177
212
  base_url: base_url.val(),
178
213
  }, function(res) {
179
214
  if (!res.error) {
180
- genExternalSetOptions(external_set_select, res.sets) // sets is [[name, spec]...]
215
+ genExternalSetOptions(external_set_select, res.sets);
181
216
  } else {
182
- setError(external_set_select, res.error)
217
+ setError(external_set_select, res.error);
183
218
  }
184
219
 
185
- refresh_button.html(initial_button_text)
186
- refresh_button.attr('disabled', false)
187
- })
220
+ refresh_button.html(initial_button_text);
221
+ refresh_button.attr('disabled', false);
222
+ });
188
223
  }
189
224
 
190
225
  function genExternalSetOptions(selector, sets) {
191
- out = '<option value="">- Select One -</option>'
226
+ out = '<option value="">- Select One -</option>';
192
227
 
193
228
  out += sets.map(function(set) {
194
- return '<option value="'+set[1]+'">'+set[0]+'</option>'
195
- })
229
+ return '<option value="'+set[1]+'">'+set[0]+'</option>';
230
+ });
196
231
 
197
- selector.html(out)
198
- selector.attr('disabled', false)
232
+ selector.html(out);
233
+ selector.attr('disabled', false);
199
234
  }
200
235
 
201
236
  function setError(selector, error) {
202
- selector.html('<option value="none">Error - Please enter Base URL and try again</option>')
203
- selector.attr('disabled', true)
237
+ selector.html('<option value="none">Error - Please enter Base URL and try again</option>');
238
+ selector.attr('disabled', true);
204
239
  }
205
240
 
206
- $(document).on({'ready': prepBulkrax, 'turbolinks:load': prepBulkrax})
241
+ $(document).on({'ready': prepBulkrax, 'turbolinks:load': prepBulkrax});
@@ -78,11 +78,13 @@ module Bulkrax
78
78
 
79
79
  # POST /importers
80
80
  # rubocop:disable Metrics/MethodLength
81
+ # rubocop:disable Metrics/AbcSize
81
82
  def create
82
83
  # rubocop:disable Style/IfInsideElse
83
84
  if api_request?
84
85
  return return_json_response unless valid_create_params?
85
86
  end
87
+ uploads = Hyrax::UploadedFile.find(params[:uploaded_files]) if params[:uploaded_files].present?
86
88
  file = file_param
87
89
  cloud_files = cloud_params
88
90
 
@@ -93,7 +95,7 @@ module Bulkrax
93
95
  # on a new import otherwise it only gets updated during the update path
94
96
  @importer.parser_fields['update_files'] = true if params[:commit] == 'Create and Import'
95
97
  if @importer.save
96
- files_for_import(file, cloud_files)
98
+ files_for_import(file, cloud_files, uploads)
97
99
  if params[:commit] == 'Create and Import'
98
100
  Bulkrax::ImporterJob.send(@importer.parser.perform_method, @importer.id)
99
101
  render_request('Importer was successfully created and import has been queued.')
@@ -112,6 +114,7 @@ module Bulkrax
112
114
  end
113
115
  # rubocop:enable Style/IfInsideElse
114
116
  end
117
+ # rubocop:enable Metrics/AbcSize
115
118
 
116
119
  # PATCH/PUT /importers/1
117
120
  # # @todo refactor so as to not need to disable rubocop
@@ -120,7 +123,7 @@ module Bulkrax
120
123
  if api_request?
121
124
  return return_json_response unless valid_update_params?
122
125
  end
123
-
126
+ uploads = Hyrax::UploadedFile.find(params[:uploaded_files]) if params[:uploaded_files].present?
124
127
  file = file_param
125
128
  cloud_files = cloud_params
126
129
 
@@ -128,7 +131,7 @@ module Bulkrax
128
131
  field_mapping_params if params[:importer][:parser_fields].present?
129
132
 
130
133
  if @importer.update(importer_params)
131
- files_for_import(file, cloud_files) unless file.nil? && cloud_files.nil?
134
+ files_for_import(file, cloud_files, uploads)
132
135
  # do not perform the import
133
136
  unless params[:commit] == 'Update Importer'
134
137
  set_files_parser_fields
@@ -218,8 +221,9 @@ module Bulkrax
218
221
 
219
222
  private
220
223
 
221
- def files_for_import(file, cloud_files)
222
- return if file.blank? && cloud_files.blank?
224
+ def files_for_import(file, cloud_files, uploads)
225
+ return if file.blank? && cloud_files.blank? && uploads.blank?
226
+
223
227
  @importer[:parser_fields]['import_file_path'] = @importer.parser.write_import_file(file) if file.present?
224
228
  if cloud_files.present?
225
229
  @importer[:parser_fields]['cloud_file_paths'] = cloud_files
@@ -229,6 +233,13 @@ module Bulkrax
229
233
  target = @importer.parser.retrieve_cloud_files(cloud_files, @importer)
230
234
  @importer[:parser_fields]['import_file_path'] = target if target.present?
231
235
  end
236
+
237
+ if uploads.present?
238
+ uploads.each do |upload|
239
+ @importer[:parser_fields]['import_file_path'] = @importer.parser.write_import_file(upload.file.file)
240
+ end
241
+ end
242
+
232
243
  @importer.save
233
244
  end
234
245
 
@@ -165,7 +165,7 @@ module Bulkrax
165
165
  end
166
166
 
167
167
  def delete(_user)
168
- find&.delete
168
+ find&.delete(eradicate: true)
169
169
  end
170
170
 
171
171
  private
@@ -10,11 +10,11 @@ module Bulkrax
10
10
  om = parent.ordered_members.to_a
11
11
  om.delete(file_set)
12
12
  parent.ordered_members = om
13
- elsif parent.respond_to?(:member_ids)
13
+ parent.save
14
+ elsif parent&.respond_to?(:member_ids)
14
15
  parent.member_ids.delete(file_set.id)
15
16
  Hyrax.persister.save(resource: parent)
16
17
  end
17
- parent.save
18
18
  end
19
19
 
20
20
  super
@@ -41,9 +41,16 @@
41
41
  <p>File upload and Cloud File upload must be a Zip file containing a single BagIt Bag, or a folder containing multiple BagIt Bags.</p>
42
42
  <p>The Server Path can point to a BagIt Bag, a folder containing BagIt Bags, or a zip file containing either.</p>
43
43
 
44
- <%= fi.input :file_style, collection: ['Upload a File', 'Specify a Path on the Server', 'Add Cloud File'], as: :radio_buttons, label: false %>
44
+ <%= fi.input :file_style,
45
+ collection: ['Upload a File', 'Specify a Path on the Server'] +
46
+ (defined?(::Hyrax) && Hyrax.config.browse_everything? ? ['Add Cloud File'] : []),
47
+ as: :radio_buttons, label: false %>
45
48
  <div id='file_upload'>
46
- <%= fi.input 'file', as: :file, input_html: {accept: 'application/zip'} %><br />
49
+ <% if defined?(::Hyrax) %>
50
+ <%= render 'bulkrax/importers/file_uploader', accepted_file_types: 'application/zip' %>
51
+ <% else %>
52
+ <%= fi.input 'file', as: :file, input_html: {accept: 'application/zip'} %><br />
53
+ <% end %>
47
54
  </div>
48
55
  <div id='file_path'>
49
56
  <%= fi.input :import_file_path, as: :string, input_html: { value: importer.parser_fields['import_file_path'] } %>
@@ -53,4 +60,4 @@
53
60
  <%= render 'browse_everything', form: form %>
54
61
  <% end %>
55
62
  </div>
56
- </div>
63
+ </div>
@@ -1,5 +1,4 @@
1
1
  <div class='csv_fields'>
2
-
3
2
  <%= fi.input :visibility,
4
3
  label: 'Default Visibility',
5
4
  collection: [
@@ -11,7 +10,6 @@
11
10
  input_html: { class: 'form-control' },
12
11
  hint: 'If your CSV includes the visibility field, it will override the default setting.'
13
12
  %>
14
-
15
13
  <% if defined?(::Hyrax) %>
16
14
  <% rights_statements = Hyrax.config.rights_statement_service_class.new %>
17
15
  <%= fi.input :rights_statement,
@@ -24,26 +22,32 @@
24
22
  %>
25
23
  <%= fi.input :override_rights_statement, as: :boolean, hint: 'If checked, always use the selected rights statment. If unchecked, use rights or rights_statement from the record and only use the provided value if dc:rights is blank.', input_html: { checked: (importer.parser_fields['override_rights_statement'] == "1") } %>
26
24
  <% end %>
27
- <h4>Add CSV File to Import:</h4>
25
+ <h4>Add CSV or ZIP File to Import:</h4>
28
26
  <%# accept a single file upload; data files and bags will need to be added another way %>
29
-
30
27
  <% file_style_list = ['Upload a File', 'Specify a Path on the Server'] %>
31
28
  <% file_style_list << 'Existing Entries' unless importer.new_record? %>
32
29
  <%= fi.input :file_style, collection: file_style_list, as: :radio_buttons, label: false %>
30
+
33
31
  <div id='file_upload'>
34
- <%= fi.input 'file', as: :file, input_html: { accept: 'text/csv,application/zip,application/gzip' } %><br />
32
+ <% if defined?(::Hyrax) %>
33
+ <%= render 'bulkrax/importers/file_uploader', accepted_file_types: 'text/csv,application/zip,application/gzip' %>
34
+ <% else %>
35
+ <%= fi.input 'file', as: :file, input_html: { accept: 'text/csv,application/zip,application/gzip' } %><br />
36
+ <% end %>
35
37
  </div>
38
+
36
39
  <div id='file_path'>
37
40
  <%= fi.input :import_file_path, as: :string, input_html: { value: importer.parser_fields['import_file_path'] } %>
38
41
  </div>
42
+
39
43
  <div id='existing_options'>
40
44
  <%= fi.collection_check_boxes :entry_statuses, [['Failed'], ['Pending'], ['Skipped'], ['Deleted'], ['Complete']], :first, :first %>
41
45
  </div>
42
-
46
+
43
47
  <% if defined?(::Hyrax) && Hyrax.config.browse_everything? %>
44
- <h4>Add Files to Import:</h4>
45
- <p>Choose files to upload. The filenames must be unique, and the filenames must be referenced in a column called 'file' in the accompanying CSV file.</p>
48
+ <h4>Add Files to Import:</h4>
49
+ <p>Choose files to upload. The filenames must be unique, and the filenames must be referenced in a column called 'file' in the accompanying CSV file.</p>
46
50
  <%= render 'browse_everything', form: form %>
47
51
  <% end %>
48
52
  <br />
49
- </div>
53
+ </div>
@@ -0,0 +1,37 @@
1
+ <div class="fileupload-bulkrax">
2
+ <noscript><input type="hidden" name="redirect" value="<%= main_app.root_path %>" /></noscript>
3
+ <table role="presentation" class="table table-striped"><tbody class="files"></tbody></table>
4
+ <div class="fileupload-buttonbar">
5
+ <div class="row">
6
+ <div class="col-12">
7
+ <div class="fileinput-button" id="add-files">
8
+ <input id="addfiles" type="file" style="display:none;" name="files[]"
9
+ accept="<%= accepted_file_types || 'text/csv,application/zip,application/gzip' %>" multiple />
10
+ <button type="button" class="btn btn-success" onclick="document.getElementById('addfiles').click();">
11
+ <span class="fa fa-plus"></span>
12
+ <span>Add Files</span>
13
+ </button>
14
+ </div>
15
+ <button type="reset" id="file-upload-cancel-btn" class="btn btn-warning cancel">
16
+ <span class="fa fa-ban"></span>
17
+ <span>Cancel Upload</span>
18
+ </button>
19
+ <span class="fileupload-process"></span>
20
+ </div>
21
+ </div>
22
+ <div class="row">
23
+ <div class="col-12">
24
+ <div class="fileupload-progress fade">
25
+ <div class="progress" role="progressbar" aria-valuemin="0" aria-valuemax="100">
26
+ <div class="progress-bar progress-bar-striped progress-bar-animated bg-success" style="width:0%;"></div>
27
+ </div>
28
+ <div class="progress-extended">&nbsp;</div>
29
+ </div>
30
+ </div>
31
+ </div>
32
+ </div>
33
+ <div class="dropzone">
34
+ Drop files here to upload
35
+ </div>
36
+ <%= render 'hyrax/uploads/js_templates' %>
37
+ </div>
@@ -47,16 +47,22 @@
47
47
  <p>File upload and Cloud File upload MUST be a either a single XML file (for metadata only import) OR a Zip file containing the XML files and data files, each in a separate folder.</p>
48
48
  <p>The Server Path can point to a folder containing XML files and data files to import, or direct to the XML file itself.</p>
49
49
 
50
- <%= fi.input :file_style, collection: ['Upload a File', 'Specify a Path on the Server', 'Add Cloud File'], as: :radio_buttons, label: false %>
50
+ <%= fi.input :file_style,
51
+ collection: ['Upload a File', 'Specify a Path on the Server'] +
52
+ (defined?(::Hyrax) && Hyrax.config.browse_everything? ? ['Add Cloud File'] : []),
53
+ as: :radio_buttons, label: false %>
51
54
  <div id='file_upload'>
52
- <%= fi.input 'file', as: :file, input_html: {accept: ['application/zip', 'application/xml']} %><br />
55
+ <% if defined?(::Hyrax) %>
56
+ <%= render 'bulkrax/importers/file_uploader', accepted_file_types: 'application/zip,application/xml' %>
57
+ <% else %>
58
+ <%= fi.input 'file', as: :file, input_html: {accept: ['application/zip', 'application/xml']} %><br />
59
+ <% end%>
53
60
  </div>
54
61
  <div id='file_path'>
55
62
  <%= fi.input :import_file_path, as: :string, input_html: { value: importer.parser_fields['import_file_path'] } %>
56
63
  </div>
57
64
  <div id='cloud'>
58
65
  <% if defined?(::Hyrax) && Hyrax.config.browse_everything? %>
59
- <%= render 'browse_everything', form: form %>
60
66
  <% end %>
61
67
  </div>
62
- </div>
68
+ </div>
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bulkrax
4
- VERSION = '8.2.0'
4
+ VERSION = '8.3.0'
5
5
  end
data/lib/bulkrax.rb CHANGED
@@ -98,7 +98,20 @@ module Bulkrax
98
98
  attr_writer :collection_model_class
99
99
 
100
100
  def collection_model_internal_resource
101
- collection_model_class.try(:internal_resource) || collection_model_class.to_s
101
+ # WARN: Using #try on :internal_resource can yield unexpected results.
102
+ # If the method is undefined, it can return a truthy value instead of
103
+ # the typical nil.
104
+ #
105
+ # E.g.
106
+ # ```ruby
107
+ # Hyrax::FileSet.try(:internal_resource) || 'hi'
108
+ # => #<Dry::Types::Result::Failure input=:internal_resource error=...
109
+ # ```
110
+ if collection_model_class.respond_to?(:internal_resource)
111
+ collection_model_class.internal_resource
112
+ else
113
+ collection_model_class.to_s
114
+ end
102
115
  end
103
116
 
104
117
  def file_model_class
@@ -108,7 +121,20 @@ module Bulkrax
108
121
  attr_writer :file_model_class
109
122
 
110
123
  def file_model_internal_resource
111
- file_model_class.try(:internal_resource) || file_model_class.to_s
124
+ # WARN: Using #try on :internal_resource can yield unexpected results.
125
+ # If the method is undefined, it can return a truthy value instead of
126
+ # the typical nil.
127
+ #
128
+ # E.g.
129
+ # ```ruby
130
+ # Hyrax::FileSet.try(:internal_resource) || 'hi'
131
+ # => #<Dry::Types::Result::Failure input=:internal_resource error=...
132
+ # ```
133
+ if file_model_class.respond_to?(:internal_resource)
134
+ file_model_class.internal_resource
135
+ else
136
+ file_model_class.to_s
137
+ end
112
138
  end
113
139
 
114
140
  def curation_concerns
@@ -118,7 +144,18 @@ module Bulkrax
118
144
  attr_writer :curation_concerns
119
145
 
120
146
  def curation_concern_internal_resources
121
- curation_concerns.map { |cc| cc.try(:internal_resource) || cc.to_s }.uniq
147
+ curation_concerns.map do |cc|
148
+ # WARN: Using #try on :internal_resource can yield unexpected results.
149
+ # If the method is undefined, it can return a truthy value instead of
150
+ # the typical nil.
151
+ #
152
+ # E.g.
153
+ # ```ruby
154
+ # Hyrax::FileSet.try(:internal_resource) || 'hi'
155
+ # => #<Dry::Types::Result::Failure input=:internal_resource error=...
156
+ # ```
157
+ cc.respond_to?(:internal_resource) ? cc.internal_resource : cc.to_s
158
+ end.uniq
122
159
  end
123
160
 
124
161
  attr_writer :ingest_queue_name
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: 8.2.0
4
+ version: 8.3.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: 2024-09-19 00:00:00.000000000 Z
11
+ date: 2024-12-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -134,14 +134,14 @@ dependencies:
134
134
  requirements:
135
135
  - - "~>"
136
136
  - !ruby/object:Gem::Version
137
- version: 3.2.4
137
+ version: '5.0'
138
138
  type: :runtime
139
139
  prerelease: false
140
140
  version_requirements: !ruby/object:Gem::Requirement
141
141
  requirements:
142
142
  - - "~>"
143
143
  - !ruby/object:Gem::Version
144
- version: 3.2.4
144
+ version: '5.0'
145
145
  - !ruby/object:Gem::Dependency
146
146
  name: loofah
147
147
  requirement: !ruby/object:Gem::Requirement
@@ -428,6 +428,7 @@ files:
428
428
  - app/views/bulkrax/importers/_csv_fields.html.erb
429
429
  - app/views/bulkrax/importers/_edit_form_buttons.html.erb
430
430
  - app/views/bulkrax/importers/_edit_item_buttons.html.erb
431
+ - app/views/bulkrax/importers/_file_uploader.html.erb
431
432
  - app/views/bulkrax/importers/_form.html.erb
432
433
  - app/views/bulkrax/importers/_oai_fields.html.erb
433
434
  - app/views/bulkrax/importers/_xml_fields.html.erb
@@ -518,7 +519,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
518
519
  - !ruby/object:Gem::Version
519
520
  version: '0'
520
521
  requirements: []
521
- rubygems_version: 3.4.10
522
+ rubygems_version: 3.4.20
522
523
  signing_key:
523
524
  specification_version: 4
524
525
  summary: Import and export tool for Hyrax and Hyku