bulkrax 4.4.0 → 5.1.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/bulkrax/entries_controller.rb +9 -2
  3. data/app/controllers/bulkrax/exporters_controller.rb +18 -9
  4. data/app/controllers/bulkrax/importers_controller.rb +15 -6
  5. data/app/factories/bulkrax/object_factory.rb +52 -3
  6. data/app/helpers/bulkrax/application_helper.rb +1 -1
  7. data/app/helpers/bulkrax/importers_helper.rb +2 -2
  8. data/app/jobs/bulkrax/create_relationships_job.rb +75 -59
  9. data/app/jobs/bulkrax/delete_job.rb +1 -1
  10. data/app/jobs/bulkrax/export_work_job.rb +2 -2
  11. data/app/jobs/bulkrax/import_file_set_job.rb +2 -1
  12. data/app/jobs/bulkrax/import_work_job.rb +13 -5
  13. data/app/jobs/bulkrax/importer_job.rb +1 -1
  14. data/app/matchers/bulkrax/application_matcher.rb +4 -2
  15. data/app/models/bulkrax/csv_entry.rb +15 -3
  16. data/app/models/bulkrax/entry.rb +2 -1
  17. data/app/models/bulkrax/exporter.rb +15 -7
  18. data/app/models/bulkrax/importer.rb +4 -4
  19. data/app/models/bulkrax/importer_run.rb +6 -0
  20. data/app/models/bulkrax/oai_entry.rb +54 -8
  21. data/app/models/bulkrax/pending_relationship.rb +4 -0
  22. data/app/models/bulkrax/rdf_entry.rb +1 -1
  23. data/app/models/bulkrax/xml_entry.rb +54 -12
  24. data/app/models/concerns/bulkrax/dynamic_record_lookup.rb +2 -0
  25. data/app/models/concerns/bulkrax/file_factory.rb +9 -3
  26. data/app/models/concerns/bulkrax/import_behavior.rb +17 -10
  27. data/app/models/concerns/bulkrax/status_info.rb +9 -4
  28. data/app/parsers/bulkrax/application_parser.rb +7 -1
  29. data/app/parsers/bulkrax/bagit_parser.rb +1 -1
  30. data/app/parsers/bulkrax/csv_parser.rb +10 -3
  31. data/app/parsers/bulkrax/xml_parser.rb +6 -0
  32. data/app/views/bulkrax/exporters/_form.html.erb +33 -17
  33. data/app/views/bulkrax/exporters/edit.html.erb +1 -1
  34. data/app/views/bulkrax/exporters/new.html.erb +1 -1
  35. data/app/views/bulkrax/importers/_form.html.erb +5 -5
  36. data/app/views/hyrax/dashboard/sidebar/_bulkrax_sidebar_additions.html.erb +3 -1
  37. data/app/views/hyrax/dashboard/sidebar/_repository_content.html.erb +24 -21
  38. data/lib/bulkrax/entry_spec_helper.rb +173 -0
  39. data/lib/bulkrax/version.rb +1 -1
  40. data/lib/bulkrax.rb +53 -0
  41. data/lib/generators/bulkrax/install_generator.rb +20 -0
  42. data/lib/generators/bulkrax/templates/config/initializers/bulkrax.rb +3 -1
  43. metadata +9 -8
@@ -69,7 +69,7 @@ module Bulkrax
69
69
  end
70
70
 
71
71
  def workflow_status_list
72
- Sipity::WorkflowState.all.map { |s| [s.name&.titleize, s.name] }.uniq
72
+ Sipity::WorkflowState.all.map { |s| [s.name&.titleize, s.name] }.uniq if defined?(::Hyrax)
73
73
  end
74
74
 
75
75
  # If field_mapping is empty, setup a default based on the export_properties
@@ -84,12 +84,20 @@ module Bulkrax
84
84
  end
85
85
 
86
86
  def export_from_list
87
- [
88
- [I18n.t('bulkrax.exporter.labels.importer'), 'importer'],
89
- [I18n.t('bulkrax.exporter.labels.collection'), 'collection'],
90
- [I18n.t('bulkrax.exporter.labels.worktype'), 'worktype'],
91
- [I18n.t('bulkrax.exporter.labels.all'), 'all']
92
- ]
87
+ if defined?(::Hyrax)
88
+ [
89
+ [I18n.t('bulkrax.exporter.labels.importer'), 'importer'],
90
+ [I18n.t('bulkrax.exporter.labels.collection'), 'collection'],
91
+ [I18n.t('bulkrax.exporter.labels.worktype'), 'worktype'],
92
+ [I18n.t('bulkrax.exporter.labels.all'), 'all']
93
+ ]
94
+ else
95
+ [
96
+ [I18n.t('bulkrax.exporter.labels.importer'), 'importer'],
97
+ [I18n.t('bulkrax.exporter.labels.collection'), 'collection'],
98
+ [I18n.t('bulkrax.exporter.labels.all'), 'all']
99
+ ]
100
+ end
93
101
  end
94
102
 
95
103
  def export_type_list
@@ -15,7 +15,7 @@ module Bulkrax
15
15
  has_many :entries, as: :importerexporter, dependent: :destroy
16
16
 
17
17
  validates :name, presence: true
18
- validates :admin_set_id, presence: true
18
+ validates :admin_set_id, presence: true if defined?(::Hyrax)
19
19
  validates :parser_klass, presence: true
20
20
 
21
21
  delegate :valid_import?, :write_errored_entries_file, :visibility, to: :parser
@@ -47,12 +47,12 @@ module Bulkrax
47
47
  if importer_run.failed_records.positive?
48
48
  if importer_run.invalid_records.present?
49
49
  e = Bulkrax::ImportFailed.new('Failed with Invalid Records', importer_run.invalid_records.split("\n"))
50
- importer_run.importer.status_info(e)
50
+ importer_run.importer.set_status_info(e)
51
51
  else
52
- importer_run.importer.status_info('Complete (with failures)')
52
+ importer_run.importer.set_status_info('Complete (with failures)')
53
53
  end
54
54
  else
55
- importer_run.importer.status_info('Complete')
55
+ importer_run.importer.set_status_info('Complete')
56
56
  end
57
57
  end
58
58
 
@@ -9,5 +9,11 @@ module Bulkrax
9
9
  def parents
10
10
  pending_relationships.pluck(:parent_id).uniq
11
11
  end
12
+
13
+ def user
14
+ # An importer might not have a user, the CLI ingest need not assign a user. As such, we
15
+ # fallback to the configured user.
16
+ importer.user || Bulkrax.fallback_user_for_importer_exporter_processing
17
+ end
12
18
  end
13
19
  end
@@ -5,10 +5,19 @@ require 'ostruct'
5
5
 
6
6
  module Bulkrax
7
7
  class OaiEntry < Entry
8
- serialize :raw_metadata, JSON
8
+ serialize :raw_metadata, Bulkrax::NormalizedJson
9
9
 
10
10
  delegate :record, to: :raw_record
11
11
 
12
+ # @api private
13
+ #
14
+ # Included to assist in testing; namely so that you can copy down an OAI entry, store it locally,
15
+ # and then manually construct an {OAI::GetRecordResponse}.
16
+ #
17
+ # @see Bulkrax::EntrySpecHelper.oai_entry_for
18
+ attr_writer :raw_record
19
+
20
+ # @return [OAI::GetRecordResponse]
12
21
  def raw_record
13
22
  @raw_record ||= client.get_record(identifier: identifier, metadata_prefix: parser.parser_fields['metadata_prefix'])
14
23
  end
@@ -28,13 +37,16 @@ module Bulkrax
28
37
  def build_metadata
29
38
  self.parsed_metadata = {}
30
39
  self.parsed_metadata[work_identifier] = [record.header.identifier]
40
+ self.raw_metadata = { record: record.metadata.to_s, header: record.header.to_s }
31
41
 
32
- record.metadata.children.each do |child|
33
- child.children.each do |node|
34
- add_metadata(node.name, node.content)
35
- end
36
- end
37
- add_metadata('thumbnail_url', thumbnail_url)
42
+ # We need to establish the #factory_class before we proceed with the metadata. See
43
+ # https://github.com/samvera-labs/bulkrax/issues/702 for further details.
44
+ #
45
+ # tl;dr - if we don't have the right factory_class we might skip properties that are
46
+ # specifically assigned to the factory class
47
+ establish_factory_class
48
+ add_metadata_from_record
49
+ add_thumbnail_url
38
50
 
39
51
  add_visibility
40
52
  add_rights_statement
@@ -53,11 +65,43 @@ module Bulkrax
53
65
  end
54
66
  end
55
67
 
68
+ # To ensure we capture the correct parse data, we first need to establish the factory_class.
69
+ # @see https://github.com/samvera-labs/bulkrax/issues/702
70
+ def establish_factory_class
71
+ model_field_names = parser.model_field_mappings
72
+
73
+ each_candidate_metadata_node do |node|
74
+ next unless model_field_names.include?(node.name)
75
+ add_metadata(node.name, node.content)
76
+ end
77
+ end
78
+
79
+ def add_metadata_from_record
80
+ each_candidate_metadata_node do |node|
81
+ add_metadata(node.name, node.content)
82
+ end
83
+ end
84
+
85
+ # A method that you could override to better handle the shape of the record's metadata.
86
+ # @yieldparam node [Object<#name, #content>]
87
+ def each_candidate_metadata_node
88
+ record.metadata.children.each do |child|
89
+ child.children.each do |node|
90
+ yield(node)
91
+ end
92
+ end
93
+ end
94
+
95
+ def add_thumbnail_url
96
+ add_metadata('thumbnail_url', thumbnail_url)
97
+ end
98
+
56
99
  # Retrieve list of collections for the entry; add to collection_ids
57
100
  # If OAI-PMH doesn't return setSpec in the headers for GetRecord, use parser.collection_name
58
101
  # in this case, if 'All' is selected, records will not be added to a collection.
59
102
  def find_collection_ids
60
- return self.collection_ids if collections_created?
103
+ return self.collection_ids if defined?(@called_find_collection_ids)
104
+
61
105
  if sets.blank? || parser.collection_name != 'all'
62
106
  collection = find_collection(importerexporter.unique_collection_identifier(parser.collection_name))
63
107
  self.collection_ids << collection.id if collection.present? && !self.collection_ids.include?(collection.id)
@@ -67,6 +111,8 @@ module Bulkrax
67
111
  self.collection_ids << c.id if c.present? && !self.collection_ids.include?(c.id)
68
112
  end
69
113
  end
114
+
115
+ @called_find_collection_ids = true
70
116
  return self.collection_ids
71
117
  end
72
118
  end
@@ -3,5 +3,9 @@
3
3
  module Bulkrax
4
4
  class PendingRelationship < ApplicationRecord
5
5
  belongs_to :importer_run
6
+
7
+ # Ideally we wouldn't have a column named "order", as it is a reserved SQL term. However, if we
8
+ # quote the column, all is well...for the application.
9
+ scope :ordered, -> { order("#{quoted_table_name}.#{connection.quote_column_name('order')}") }
6
10
  end
7
11
  end
@@ -3,7 +3,7 @@
3
3
  require 'rdf'
4
4
  module Bulkrax
5
5
  class RdfEntry < Entry
6
- serialize :raw_metadata, JSON
6
+ serialize :raw_metadata, Bulkrax::NormalizedJson
7
7
 
8
8
  def self.read_data(path)
9
9
  RDF::Reader.open(path)
@@ -4,7 +4,7 @@ require 'nokogiri'
4
4
  module Bulkrax
5
5
  # Generic XML Entry
6
6
  class XmlEntry < Entry
7
- serialize :raw_metadata, JSON
7
+ serialize :raw_metadata, Bulkrax::NormalizedJson
8
8
 
9
9
  def self.fields_from_data(data); end
10
10
 
@@ -43,15 +43,14 @@ module Bulkrax
43
43
  raise StandardError, "Missing source identifier (#{source_identifier})" if self.raw_metadata[source_identifier].blank?
44
44
  self.parsed_metadata = {}
45
45
  self.parsed_metadata[work_identifier] = [self.raw_metadata[source_identifier]]
46
- xml_elements.each do |element_name|
47
- elements = record.xpath("//*[name()='#{element_name}']")
48
- next if elements.blank?
49
- elements.each do |el|
50
- el.children.map(&:content).each do |content|
51
- add_metadata(element_name, content) if content.present?
52
- end
53
- end
54
- end
46
+
47
+ # We need to establish the #factory_class before we proceed with the metadata. See
48
+ # https://github.com/samvera-labs/bulkrax/issues/702 for further details.
49
+ #
50
+ # tl;dr - if we don't have the right factory_class we might skip properties that are
51
+ # specifically assigned to the factory class
52
+ establish_factory_class
53
+ add_metadata_from_record
55
54
  add_visibility
56
55
  add_rights_statement
57
56
  add_admin_set_id
@@ -63,11 +62,54 @@ module Bulkrax
63
62
  self.parsed_metadata
64
63
  end
65
64
 
66
- # Grab the class from the real parser
67
- def xml_elements
65
+ def establish_factory_class
66
+ model_field_names = parser.model_field_mappings
67
+
68
+ each_candidate_metadata_node_name_and_content(elements: parser.model_field_mappings) do |name, content|
69
+ next unless model_field_names.include?(name)
70
+ add_metadata(name, content)
71
+ end
72
+ end
73
+
74
+ def add_metadata_from_record
75
+ each_candidate_metadata_node_name_and_content do |name, content|
76
+ add_metadata(name, content)
77
+ end
78
+ end
79
+
80
+ def each_candidate_metadata_node_name_and_content(elements: field_mapping_from_values_for_xml_element_names)
81
+ elements.each do |name|
82
+ # NOTE: the XML element name's case matters
83
+ nodes = record.xpath("//*[name()='#{name}']")
84
+ next if nodes.empty?
85
+
86
+ nodes.each do |node|
87
+ node.children.each do |content|
88
+ next if content.to_s.blank?
89
+
90
+ yield(name, content.to_s)
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ # Returns the explicitly declared "from" key's value of each parser's element's value. (Yes, I
97
+ # would like a proper class for the thing I just tried to describe.)
98
+ #
99
+ # @return [Array<String>]
100
+ #
101
+ # @todo Additionally, we may want to revisit the XML parser fundamental logic; namely we only
102
+ # parse nodes that are explicitly declared with in the `from`. This is a bit different
103
+ # than other parsers, in that they will make assumptions about each encountered column (in
104
+ # the case of CSV) or node (in the case of OAI). tl;dr - Here there be dragons.
105
+ def field_mapping_from_values_for_xml_element_names
68
106
  Bulkrax.field_mappings[self.importerexporter.parser_klass].map do |_k, v|
69
107
  v[:from]
70
108
  end.flatten.compact.uniq
71
109
  end
110
+
111
+ # Included for potential downstream adopters
112
+ alias xml_elements field_mapping_from_values_for_xml_element_names
113
+ deprecation_deprecate xml_elements: "Use '#{self}#field_mapping_from_values_for_xml_element_names' instead"
72
114
  end
73
115
  end
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bulkrax
4
+ # TODO: Extract methods to class methods; there's no reason for these methods to be a mixin.
5
+ # TODO: Add specs to test in isolation
4
6
  module DynamicRecordLookup
5
7
  # Search entries, collections, and every available work type for a record that
6
8
  # has the provided identifier.
@@ -45,9 +45,15 @@ module Bulkrax
45
45
  end
46
46
 
47
47
  def new_remote_files
48
- return if object.is_a? FileSet
49
-
50
- @new_remote_files ||= if object.present? && object.file_sets.present?
48
+ @new_remote_files ||= if object.is_a? FileSet
49
+ parsed_remote_files.select do |file|
50
+ # is the url valid?
51
+ is_valid = file[:url]&.match(URI::ABS_URI)
52
+ # does the file already exist
53
+ is_existing = object.import_url && object.import_url == file[:url]
54
+ is_valid && !is_existing
55
+ end
56
+ elsif object.present? && object.file_sets.present?
51
57
  parsed_remote_files.select do |file|
52
58
  # is the url valid?
53
59
  is_valid = file[:url]&.match(URI::ABS_URI)
@@ -117,23 +117,30 @@ module Bulkrax
117
117
  Bulkrax.qa_controlled_properties.each do |field|
118
118
  next if parsed_metadata[field].blank?
119
119
 
120
- parsed_metadata[field].each_with_index do |value, i|
121
- next if value.blank?
122
-
123
- if (validated_uri_value = validate_value(value, field))
124
- parsed_metadata[field][i] = validated_uri_value
125
- else
126
- debug_msg = %(Unable to locate active authority ID "#{value}" in config/authorities/#{field.pluralize}.yml)
127
- Rails.logger.debug(debug_msg)
128
- error_msg = %("#{value}" is not a valid and/or active authority ID for the :#{field} field)
129
- raise ::StandardError, error_msg
120
+ if multiple?(field)
121
+ parsed_metadata[field].each_with_index do |value, i|
122
+ next if value.blank?
123
+ parsed_metadata[field][i] = sanitize_controlled_uri_value(field, value)
130
124
  end
125
+ else
126
+ parsed_metadata[field] = sanitize_controlled_uri_value(field, parsed_metadata[field])
131
127
  end
132
128
  end
133
129
 
134
130
  true
135
131
  end
136
132
 
133
+ def sanitize_controlled_uri_value(field, value)
134
+ if (validated_uri_value = validate_value(value, field))
135
+ validated_uri_value
136
+ else
137
+ debug_msg = %(Unable to locate active authority ID "#{value}" in config/authorities/#{field.pluralize}.yml)
138
+ Rails.logger.debug(debug_msg)
139
+ error_msg = %("#{value}" is not a valid and/or active authority ID for the :#{field} field)
140
+ raise ::StandardError, error_msg
141
+ end
142
+ end
143
+
137
144
  # @param value [String] value to validate
138
145
  # @param field [String] name of the controlled property
139
146
  # @return [String, nil] validated URI value or nil
@@ -33,16 +33,21 @@ module Bulkrax
33
33
  current_status&.created_at
34
34
  end
35
35
 
36
- def status_info(e = nil, current_run = nil)
36
+ def set_status_info(e = nil, current_run = nil)
37
+ runnable = current_run || last_run
37
38
  if e.nil?
38
- self.statuses.create!(status_message: 'Complete', runnable: current_run || last_run)
39
+ self.statuses.create!(status_message: 'Complete', runnable: runnable)
39
40
  elsif e.is_a?(String)
40
- self.statuses.create!(status_message: e, runnable: current_run || last_run)
41
+ self.statuses.create!(status_message: e, runnable: runnable)
41
42
  else
42
- self.statuses.create!(status_message: 'Failed', runnable: current_run || last_run, error_class: e.class.to_s, error_message: e.message, error_backtrace: e.backtrace)
43
+ self.statuses.create!(status_message: 'Failed', runnable: runnable, error_class: e.class.to_s, error_message: e.message, error_backtrace: e.backtrace)
43
44
  end
44
45
  end
45
46
 
47
+ alias status_info set_status_info
48
+
49
+ deprecation_deprecate status_info: "Favor Bulkrax::StatusInfo.set_status_info. We will be removing .status_info in Bulkrax v6.0.0"
50
+
46
51
  # api compatible with previous error structure
47
52
  def last_error
48
53
  return unless current_status && current_status.error_class.present?
@@ -51,6 +51,12 @@ module Bulkrax
51
51
  raise NotImplementedError, 'must be defined'
52
52
  end
53
53
 
54
+ # @api public
55
+ # @abstract Subclass and override {#file_set_entry_class} to implement behavior for the parser.
56
+ def file_set_entry_class
57
+ raise NotImplementedError, 'must be defined'
58
+ end
59
+
54
60
  # @api public
55
61
  # @abstract Subclass and override {#records} to implement behavior for the parser.
56
62
  def records(_opts = {})
@@ -153,7 +159,7 @@ module Bulkrax
153
159
  # @see #create_relationships
154
160
  def create_objects(types = [])
155
161
  types.each do |object_type|
156
- parser.send("create_#{object_type.pluralize}")
162
+ send("create_#{object_type.pluralize}")
157
163
  end
158
164
  end
159
165
 
@@ -143,7 +143,7 @@ module Bulkrax
143
143
  begin
144
144
  bag.add_file(file_name, file.path) if bag.bag_files.select { |b| b.include?(file_name) }.blank?
145
145
  rescue => e
146
- entry.status_info(e)
146
+ entry.set_status_info(e)
147
147
  status_info(e)
148
148
  end
149
149
  end
@@ -196,10 +196,13 @@ module Bulkrax
196
196
  @collection_ids = ActiveFedora::SolrService.query("has_model_ssim:Collection #{extra_filters}", method: :post, rows: 2_147_483_647).map(&:id)
197
197
  @file_set_ids = ActiveFedora::SolrService.query("has_model_ssim:FileSet #{extra_filters}", method: :post, rows: 2_147_483_647).map(&:id)
198
198
  when 'collection'
199
- @work_ids = ActiveFedora::SolrService.query("member_of_collection_ids_ssim:#{importerexporter.export_source + extra_filters} AND has_model_ssim:(#{Hyrax.config.curation_concerns.join(' OR ')})", method: :post, rows: 2_000_000_000).map(&:id)
199
+ @work_ids = ActiveFedora::SolrService.query(
200
+ "member_of_collection_ids_ssim:#{importerexporter.export_source + extra_filters} AND has_model_ssim:(#{Hyrax.config.curation_concerns.join(' OR ')})", method: :post, rows: 2_000_000_000
201
+ ).map(&:id)
200
202
  # get the parent collection and child collections
201
203
  @collection_ids = ActiveFedora::SolrService.query("id:#{importerexporter.export_source} #{extra_filters}", method: :post, rows: 2_147_483_647).map(&:id)
202
- @collection_ids += ActiveFedora::SolrService.query("has_model_ssim:Collection AND member_of_collection_ids_ssim:#{importerexporter.export_source}", method: :post, rows: 2_147_483_647).map(&:id)
204
+ @collection_ids += ActiveFedora::SolrService.query("has_model_ssim:Collection AND member_of_collection_ids_ssim:#{importerexporter.export_source}", method: :post,
205
+ rows: 2_147_483_647).map(&:id)
203
206
  find_child_file_sets(@work_ids)
204
207
  when 'worktype'
205
208
  @work_ids = ActiveFedora::SolrService.query("has_model_ssim:#{importerexporter.export_source + extra_filters}", method: :post, rows: 2_000_000_000).map(&:id)
@@ -234,7 +237,7 @@ module Bulkrax
234
237
  instance_variable_set(instance_var, ActiveFedora::SolrService.post(
235
238
  extra_filters.to_s,
236
239
  fq: [
237
- %(#{::Solrizer.solr_name(work_identifier)}:("#{complete_entry_identifiers.join('" OR "')}")),
240
+ %(#{solr_name(work_identifier)}:("#{complete_entry_identifiers.join('" OR "')}")),
238
241
  "has_model_ssim:(#{models_to_search.join(' OR ')})"
239
242
  ],
240
243
  fl: 'id',
@@ -243,6 +246,10 @@ module Bulkrax
243
246
  end
244
247
  end
245
248
 
249
+ def solr_name(base_name)
250
+ Module.const_defined?(:Solrizer) ? ::Solrizer.solr_name(base_name) : ::ActiveFedora.index_field_mapper.solr_name(base_name)
251
+ end
252
+
246
253
  def create_new_entries
247
254
  current_record_ids.each_with_index do |id, index|
248
255
  break if limit_reached?(limit, index)
@@ -12,6 +12,12 @@ module Bulkrax
12
12
  # @todo not yet supported
13
13
  def create_collections; end
14
14
 
15
+ # @todo not yet supported
16
+ def file_set_entry_class; end
17
+
18
+ # @todo not yet supported
19
+ def create_file_sets; end
20
+
15
21
  # TODO: change to differentiate between collection and work records when adding ability to import collection metadata
16
22
  def works_total
17
23
  total
@@ -11,7 +11,7 @@
11
11
  </div>
12
12
  <% end %>
13
13
 
14
- <%= form.input :name, label: t('bulkrax.exporter.labels.name') %>
14
+ <%= form.input :name, label: t('bulkrax.exporter.labels.name'), input_html: { class: 'form-control' } %>
15
15
 
16
16
  <%= form.hidden_field :user_id, value: current_user.id %>
17
17
 
@@ -19,20 +19,22 @@
19
19
  collection: form.object.export_type_list,
20
20
  label: t('bulkrax.exporter.labels.export_type'),
21
21
  required: true,
22
- prompt: 'Please select an export type' %>
22
+ prompt: 'Please select an export type',
23
+ input_html: { class: 'form-control' } %>
23
24
 
24
25
  <%= form.input :export_from,
25
26
  collection: form.object.export_from_list,
26
27
  label: t('bulkrax.exporter.labels.export_from'),
27
28
  required: true,
28
- prompt: 'Please select an export source' %>
29
+ prompt: 'Please select an export source',
30
+ input_html: { class: 'form-control' } %>
29
31
 
30
32
  <%= form.input :export_source_importer,
31
33
  label: t('bulkrax.exporter.labels.importer'),
32
34
  required: true,
33
35
  prompt: 'Select from the list',
34
36
  label_html: { class: 'importer export-source-option hidden' },
35
- input_html: { class: 'importer export-source-option hidden' },
37
+ input_html: { class: 'importer export-source-option hidden form-control' },
36
38
  collection: form.object.importers_list.sort %>
37
39
 
38
40
  <%= form.input :export_source_collection,
@@ -42,7 +44,7 @@
42
44
  placeholder: @collection&.title&.first,
43
45
  label_html: { class: 'collection export-source-option hidden' },
44
46
  input_html: {
45
- class: 'collection export-source-option hidden',
47
+ class: 'collection export-source-option hidden form-control',
46
48
  data: {
47
49
  'autocomplete-url' => '/authorities/search/collections',
48
50
  'autocomplete' => 'collection'
@@ -50,18 +52,22 @@
50
52
  }
51
53
  %>
52
54
 
53
- <%= form.input :export_source_worktype,
55
+ <% if defined?(::Hyrax) %>
56
+ <%= form.input :export_source_worktype,
54
57
  label: t('bulkrax.exporter.labels.worktype'),
55
58
  required: true,
56
59
  prompt: 'Select from the list',
57
60
  label_html: { class: 'worktype export-source-option hidden' },
58
- input_html: { class: 'worktype export-source-option hidden' },
61
+ input_html: { class: 'worktype export-source-option hidden form-control' },
59
62
  collection: Hyrax.config.curation_concerns.map {|cc| [cc.to_s, cc.to_s] } %>
63
+ <% end %>
64
+
60
65
 
61
66
  <%= form.input :limit,
62
67
  as: :integer,
63
68
  hint: 'leave blank or 0 for all records',
64
- label: t('bulkrax.exporter.labels.limit') %>
69
+ label: t('bulkrax.exporter.labels.limit'),
70
+ input_html: { class: 'form-control' } %>
65
71
 
66
72
  <%= form.input :generated_metadata?,
67
73
  as: :boolean,
@@ -76,26 +82,36 @@
76
82
  <%= form.input :date_filter,
77
83
  as: :boolean,
78
84
  label: t('bulkrax.exporter.labels.filter_by_date') %>
85
+
79
86
  <div id="date_filter_picker" class="hidden">
80
87
  <%= form.input :start_date,
81
88
  as: :date,
82
- label: t('bulkrax.exporter.labels.start_date') %>
89
+ label: t('bulkrax.exporter.labels.start_date'),
90
+ input_html: { class: 'form-control' } %>
83
91
 
84
92
  <%= form.input :finish_date,
85
93
  as: :date,
86
- label: t('bulkrax.exporter.labels.finish_date') %>
94
+ label: t('bulkrax.exporter.labels.finish_date'),
95
+ input_html: { class: 'form-control' } %>
87
96
  </div>
88
- <%= form.input :work_visibility,
89
- collection: form.object.work_visibility_list,
90
- label: t('bulkrax.exporter.labels.visibility') %>
97
+ <% if defined?(::Hyrax) %>
98
+ <%= form.input :work_visibility,
99
+ collection: form.object.work_visibility_list,
100
+ label: t('bulkrax.exporter.labels.visibility'),
101
+ input_html: { class: 'form-control' } %>
102
+ <% end %>
91
103
 
92
- <%= form.input :workflow_status,
93
- collection: form.object.workflow_status_list,
94
- label: t('bulkrax.exporter.labels.status') %>
104
+ <% if defined?(::Hyrax) %>
105
+ <%= form.input :workflow_status,
106
+ collection: form.object.workflow_status_list,
107
+ label: t('bulkrax.exporter.labels.status'),
108
+ input_html: { class: 'form-control' } %>
109
+ <% end %>
95
110
 
96
111
  <%= form.input :parser_klass,
97
112
  collection: Bulkrax.parsers.map {|p| [p[:name], p[:class_name], {'data-partial' => p[:partial]}] if p[:class_name].constantize.export_supported? }.compact,
98
- label: t('bulkrax.exporter.labels.export_format') %>
113
+ label: t('bulkrax.exporter.labels.export_format'),
114
+ input_html: { class: 'form-control' } %>
99
115
  </div>
100
116
 
101
117
  <%# Find definitions for the functions called in this script in
@@ -4,7 +4,7 @@
4
4
 
5
5
  <div class="row">
6
6
  <div class="col-md-12">
7
- <div class="panel panel-default tabs">
7
+ <div class="panel panel-default tabs exporter-form">
8
8
  <%= simple_form_for @exporter do |form| %>
9
9
  <%= render 'form', exporter: @exporter, form: form %>
10
10
  <div class="panel-footer">
@@ -4,7 +4,7 @@
4
4
 
5
5
  <div class="row">
6
6
  <div class="col-md-12">
7
- <div class="panel panel-default tabs">
7
+ <div class="panel panel-default tabs exporter-form">
8
8
  <%= simple_form_for @exporter do |form| %>
9
9
  <%= render 'form', exporter: @exporter, form: form %>
10
10
  <div class="panel-footer">
@@ -11,17 +11,17 @@
11
11
  </div>
12
12
  <% end %>
13
13
 
14
- <%= form.input :name %>
14
+ <%= form.input :name, input_html: { class: 'form-control' } %>
15
15
 
16
- <%= form.input :admin_set_id, collection: available_admin_sets %>
16
+ <%= form.input :admin_set_id, collection: available_admin_sets if defined?(::Hyrax) %>
17
17
 
18
18
  <%= form.hidden_field :user_id, value: current_user.id %>
19
19
 
20
- <%= form.input :frequency, collection: form.object.class.frequency_enums %>
20
+ <%= form.input :frequency, collection: form.object.class.frequency_enums, input_html: { class: 'form-control' } %>
21
21
 
22
- <%= form.input :limit, as: :integer, hint: 'leave blank or 0 for all records' %>
22
+ <%= form.input :limit, as: :integer, hint: 'leave blank or 0 for all records', input_html: { class: 'form-control'} %>
23
23
 
24
- <%= form.input :parser_klass, collection: Bulkrax.parsers.map {|p| [p[:name], p[:class_name], {'data-partial' => p[:partial]}]}, label: "Parser" %>
24
+ <%= form.input :parser_klass, collection: Bulkrax.parsers.map {|p| [p[:name], p[:class_name], {'data-partial' => p[:partial]}]}, label: "Parser", input_html: { class: 'form-control' } %>
25
25
 
26
26
  <%= form.fields_for :parser_fields do |fi| %>
27
27
  <div class='parser_fields'>
@@ -1,7 +1,9 @@
1
- <% if ENV.fetch('HYKU_BULKRAX_ENABLED', 'true') == 'true' %>
1
+ <% if current_ability.can_import_works? %>
2
2
  <%= menu.nav_link(bulkrax.importers_path) do %>
3
3
  <span class="fa fa-cloud-upload" aria-hidden="true"></span> <span class="sidebar-action-text"><%= t('bulkrax.admin.sidebar.importers') %></span>
4
4
  <% end %>
5
+ <% end %>
6
+ <% if current_ability.can_export_works? %>
5
7
  <%= menu.nav_link(bulkrax.exporters_path) do %>
6
8
  <span class="fa fa-cloud-download" aria-hidden="true"></span> <span class="sidebar-action-text"><%= t('bulkrax.admin.sidebar.exporters') %></span>
7
9
  <% end %>