hyrax 3.4.1 → 3.4.2
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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +26 -17
- data/.dassie/.env +1 -1
- data/.dassie/Gemfile +1 -1
- data/.dassie/app/forms/collection_resource_form.rb +8 -0
- data/.dassie/app/indexers/collection_resource_indexer.rb +8 -0
- data/.dassie/app/models/collection_resource.rb +35 -0
- data/.dassie/config/initializers/file_services.rb +4 -0
- data/.dassie/config/initializers/hyrax.rb +2 -1
- data/.dassie/config/metadata/collection_resource.yaml +23 -0
- data/.dassie/db/seeds.rb +2 -0
- data/.dassie/spec/forms/collection_resource_form_spec.rb +13 -0
- data/.dassie/spec/indexers/collection_resource_indexer_spec.rb +14 -0
- data/.dassie/spec/models/collection_resource_spec.rb +13 -0
- data/.regen +1 -1
- data/.rubocop.yml +1 -1
- data/.rubocop_fixme.yml +19 -2
- data/CONTAINERS.md +18 -13
- data/Dockerfile +2 -2
- data/app/assets/javascripts/hyrax/collections_v2.es6 +13 -0
- data/app/controllers/concerns/hyrax/collections_controller_behavior.rb +1 -3
- data/app/controllers/hyrax/dashboard/collections_controller.rb +159 -75
- data/app/controllers/hyrax/single_use_links_viewer_controller.rb +1 -1
- data/app/forms/hyrax/forms/collection_form.rb +1 -1
- data/app/forms/hyrax/forms/pcdm_collection_form.rb +29 -2
- data/app/forms/hyrax/forms/resource_form.rb +15 -1
- data/app/forms/hyrax/forms/widgets/admin_set_visibility.rb +1 -1
- data/app/indexers/hyrax/pcdm_collection_indexer.rb +0 -1
- data/app/jobs/characterize_job.rb +5 -1
- data/app/jobs/import_url_job.rb +4 -6
- data/app/jobs/valkyrie_ingest_job.rb +15 -77
- data/app/models/admin_set.rb +8 -0
- data/app/models/concerns/hyrax/collection_behavior.rb +1 -1
- data/app/models/concerns/hyrax/user.rb +11 -0
- data/app/models/concerns/hyrax/work_behavior.rb +1 -1
- data/app/models/featured_work_list.rb +0 -1
- data/app/models/hyrax/file_metadata.rb +32 -2
- data/app/models/hyrax/file_set.rb +1 -3
- data/app/models/hyrax/group.rb +19 -0
- data/app/models/hyrax/pcdm_collection.rb +0 -1
- data/app/models/job_io_wrapper.rb +1 -1
- data/app/presenters/hyrax/member_presenter_factory.rb +2 -4
- data/app/presenters/hyrax/work_show_presenter.rb +3 -3
- data/app/services/hyrax/access_control_list.rb +7 -6
- data/app/services/hyrax/adapters/nesting_index_adapter.rb +3 -3
- data/app/services/hyrax/characterization/valkyrie_characterization_service.rb +3 -5
- data/app/services/hyrax/collections/collection_member_service.rb +3 -5
- data/app/services/hyrax/listeners/file_metadata_listener.rb +11 -0
- data/app/services/hyrax/listeners/member_cleanup_listener.rb +14 -18
- data/app/services/hyrax/multiple_membership_checker.rb +2 -0
- data/app/services/hyrax/valkyrie_persist_derivatives.rb +50 -0
- data/app/services/hyrax/valkyrie_upload.rb +94 -0
- data/app/services/hyrax/workflow/workflow_importer.rb +7 -9
- data/app/services/hyrax/workflow/workflow_schema.rb +3 -5
- data/app/strategies/hyrax/strategies/yaml_strategy.rb +4 -6
- data/app/uploaders/hyrax/uploaded_file_uploader.rb +4 -4
- data/app/validators/hyrax/collection_membership_validator.rb +16 -15
- data/app/views/catalog/_index_header_list_default.html.erb +8 -1
- data/app/views/catalog/_thumbnail_list_default.html.erb +8 -3
- data/app/views/collections/edit_fields/_based_near.html.erb +7 -7
- data/app/views/hyrax/dashboard/collections/_form.html.erb +3 -2
- data/app/views/hyrax/dashboard/collections/_form_branding.html.erb +1 -0
- data/app/views/hyrax/dashboard/sidebar/_activity.html.erb +1 -1
- data/app/views/hyrax/my/works/_tabs.html.erb +6 -1
- data/chart/hyrax/Chart.yaml +10 -6
- data/chart/hyrax/templates/_helpers.tpl +4 -0
- data/chart/hyrax/templates/cron-embargo.yaml +5 -0
- data/chart/hyrax/templates/cron-lease.yaml +5 -0
- data/chart/hyrax/templates/deployment-worker.yaml +11 -0
- data/chart/hyrax/templates/ingress.yaml +7 -6
- data/chart/hyrax/values.yaml +152 -0
- data/config/features.rb +48 -50
- data/config/initializers/{valkryrie_storage.rb → storage_adapter_initializer.rb} +5 -0
- data/config/locales/hyrax.de.yml +12 -12
- data/docker-compose.yml +1 -0
- data/documentation/developing-your-hyrax-based-app.md +1 -1
- data/documentation/legacyREADME.md +1 -1
- data/hyrax.gemspec +5 -3
- data/lib/generators/hyrax/collection_resource/USAGE +20 -0
- data/lib/generators/hyrax/collection_resource/collection_resource_generator.rb +133 -0
- data/lib/generators/hyrax/collection_resource/templates/collection.rb.erb +34 -0
- data/lib/generators/hyrax/collection_resource/templates/collection_form.rb.erb +7 -0
- data/lib/generators/hyrax/collection_resource/templates/collection_form_spec.rb.erb +13 -0
- data/lib/generators/hyrax/collection_resource/templates/collection_indexer.rb.erb +7 -0
- data/lib/generators/hyrax/collection_resource/templates/collection_indexer_spec.rb.erb +13 -0
- data/lib/generators/hyrax/collection_resource/templates/collection_metadata.yaml +22 -0
- data/lib/generators/hyrax/collection_resource/templates/collection_spec.rb.erb +12 -0
- data/lib/generators/hyrax/install_generator.rb +9 -0
- data/lib/hyrax/configuration.rb +12 -0
- data/lib/hyrax/publisher.rb +4 -0
- data/lib/hyrax/specs/shared_specs/hydra_works.rb +0 -1
- data/lib/hyrax/transactions/collection_update.rb +2 -0
- data/lib/hyrax/transactions/container.rb +10 -0
- data/lib/hyrax/transactions/steps/save_collection_banner.rb +59 -0
- data/lib/hyrax/transactions/steps/save_collection_logo.rb +109 -0
- data/lib/hyrax/version.rb +1 -1
- data/lib/wings/active_fedora_converter/file_metadata_node.rb +48 -0
- data/lib/wings/active_fedora_converter/instance_builder.rb +68 -0
- data/lib/wings/active_fedora_converter.rb +3 -3
- data/lib/wings/services/custom_queries/find_file_metadata.rb +19 -8
- data/lib/wings/valkyrie/query_service.rb +4 -6
- data/template.rb +1 -1
- metadata +63 -13
- data/app/views/catalog/_index_header_list_hyrax_pcdm_collection.html.erb +0 -4
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Hyrax
|
|
4
|
+
##
|
|
5
|
+
# Casts a resource to an associated FileMetadata
|
|
6
|
+
#
|
|
7
|
+
# @param [Valkyrie::StorageAdapter::File] file
|
|
8
|
+
#
|
|
9
|
+
# @return [Hyrax::FileMetadata]
|
|
10
|
+
# @raise [ArgumentError]
|
|
11
|
+
def self.FileMetadata(file)
|
|
12
|
+
raise(ArgumentError, "Expected a Valkyrie::StorageAdapter::File; got #{file.class}: #{file}") if
|
|
13
|
+
file.is_a?(Valkyrie::Resource)
|
|
14
|
+
|
|
15
|
+
Hyrax.custom_queries.find_file_metadata_by(id: file.id)
|
|
16
|
+
rescue Hyrax::ObjectNotFoundError, Ldp::BadRequest
|
|
17
|
+
Hyrax.logger.debug('Could not find an existing metadata node for file ' \
|
|
18
|
+
"with id #{file.id}. Initializing a new one")
|
|
19
|
+
|
|
20
|
+
FileMetadata.new(file_identifier: file.id, alternative_ids: [file.id])
|
|
21
|
+
end
|
|
22
|
+
|
|
4
23
|
class FileMetadata < Valkyrie::Resource
|
|
5
24
|
# Include mime-types for Hydra Derivatives mime-type checking. We may want
|
|
6
25
|
# to move this logic someday.
|
|
@@ -39,7 +58,7 @@ module Hyrax
|
|
|
39
58
|
end
|
|
40
59
|
|
|
41
60
|
attribute :file_identifier, Valkyrie::Types::ID # id of the file stored by the storage adapter
|
|
42
|
-
attribute :alternate_ids, Valkyrie::Types::Set.of(Valkyrie::Types::ID) # id of the
|
|
61
|
+
attribute :alternate_ids, Valkyrie::Types::Set.of(Valkyrie::Types::ID) # id of the file, populated for queryability
|
|
43
62
|
attribute :file_set_id, ::Valkyrie::Types::ID # id of parent file set resource
|
|
44
63
|
|
|
45
64
|
# all remaining attributes are on AF::File metadata_node unless otherwise noted
|
|
@@ -107,7 +126,9 @@ module Hyrax
|
|
|
107
126
|
attribute :aspect_ratio, ::Valkyrie::Types::Set
|
|
108
127
|
|
|
109
128
|
# @param [ActionDispatch::Http::UploadedFile] file
|
|
129
|
+
# @deprecated Use #new instead; for removal in 4.0.0
|
|
110
130
|
def self.for(file:)
|
|
131
|
+
Deprecation.warn "#{self.class}##{__method__} is deprecated; use #new instead."
|
|
111
132
|
new(label: file.original_filename,
|
|
112
133
|
original_filename: file.original_filename,
|
|
113
134
|
mime_type: file.content_type)
|
|
@@ -155,8 +176,17 @@ module Hyrax
|
|
|
155
176
|
''
|
|
156
177
|
end
|
|
157
178
|
|
|
179
|
+
##
|
|
180
|
+
# @return [Valkyrie::StorageAdapter::File]
|
|
181
|
+
#
|
|
182
|
+
# @raise [Valkyrie::StorageAdapter::AdapterNotFoundError] if no adapter
|
|
183
|
+
# could be found matching the file_identifier's scheme
|
|
184
|
+
# @raise [Valkyrie::StorageAdapter::FileNotFound] when the file can't
|
|
185
|
+
# be found in the registered adapter
|
|
158
186
|
def file
|
|
159
|
-
|
|
187
|
+
Valkyrie::StorageAdapter
|
|
188
|
+
.adapter_for(id: file_identifier)
|
|
189
|
+
.find_by(id: file_identifier)
|
|
160
190
|
end
|
|
161
191
|
end
|
|
162
192
|
end
|
|
@@ -34,9 +34,7 @@ module Hyrax
|
|
|
34
34
|
include Hyrax::Schema(:basic_metadata)
|
|
35
35
|
|
|
36
36
|
def self.model_name(name_class: Hyrax::Name)
|
|
37
|
-
@_model_name ||=
|
|
38
|
-
name_class.new(self, nil, 'FileSet')
|
|
39
|
-
end
|
|
37
|
+
@_model_name ||= name_class.new(self, nil, 'FileSet')
|
|
40
38
|
end
|
|
41
39
|
|
|
42
40
|
class_attribute :characterization_proxy
|
data/app/models/hyrax/group.rb
CHANGED
|
@@ -7,12 +7,31 @@ module Hyrax
|
|
|
7
7
|
DEFAULT_NAME_PREFIX
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
+
##
|
|
11
|
+
# @return [Hyrax::Group]
|
|
12
|
+
def self.from_agent_key(key)
|
|
13
|
+
new(key.delete_prefix(name_prefix))
|
|
14
|
+
end
|
|
15
|
+
|
|
10
16
|
def initialize(name)
|
|
11
17
|
@name = name
|
|
12
18
|
end
|
|
13
19
|
|
|
14
20
|
attr_reader :name
|
|
15
21
|
|
|
22
|
+
##
|
|
23
|
+
# @return [Boolean]
|
|
24
|
+
def ==(other)
|
|
25
|
+
other.class == self.class && other.name == name
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
##
|
|
29
|
+
# @return [String] a local identifier for this group; for use (e.g.) in ACL
|
|
30
|
+
# data
|
|
31
|
+
def agent_key
|
|
32
|
+
self.class.name_prefix + name
|
|
33
|
+
end
|
|
34
|
+
|
|
16
35
|
def to_sipity_agent
|
|
17
36
|
sipity_agent || create_sipity_agent!
|
|
18
37
|
end
|
|
@@ -41,7 +41,6 @@ module Hyrax
|
|
|
41
41
|
#
|
|
42
42
|
class PcdmCollection < Hyrax::Resource
|
|
43
43
|
include Hyrax::Schema(:core_metadata)
|
|
44
|
-
include Hyrax::Schema(:basic_metadata)
|
|
45
44
|
|
|
46
45
|
attribute :collection_type_gid, Valkyrie::Types::String
|
|
47
46
|
attribute :member_ids, Valkyrie::Types::Array.of(Valkyrie::Types::ID).meta(ordered: true)
|
|
@@ -94,7 +94,7 @@ class JobIoWrapper < ApplicationRecord
|
|
|
94
94
|
|
|
95
95
|
def extracted_original_name
|
|
96
96
|
eon = uploaded_file.uploader.filename if uploaded_file
|
|
97
|
-
eon ||= File.basename(path) if path.present? #
|
|
97
|
+
eon ||= File.basename(path) if path.present? # NOTE: uploader.filename is `nil` with uncached remote files (e.g. AWSFile)
|
|
98
98
|
eon
|
|
99
99
|
end
|
|
100
100
|
|
|
@@ -47,13 +47,11 @@ module Hyrax
|
|
|
47
47
|
# in order.
|
|
48
48
|
# Arbitrarily maxed at 10 thousand; had to specify rows due to solr's default of 10
|
|
49
49
|
def file_set_ids
|
|
50
|
-
@file_set_ids ||=
|
|
51
|
-
Hyrax::SolrService.query("{!field f=has_model_ssim}FileSet",
|
|
50
|
+
@file_set_ids ||= Hyrax::SolrService.query("{!field f=has_model_ssim}FileSet",
|
|
52
51
|
rows: 10_000,
|
|
53
52
|
fl: Hyrax.config.id_field,
|
|
54
53
|
fq: "{!join from=ordered_targets_ssim to=id}id:\"#{id}/list_source\"")
|
|
55
|
-
|
|
56
|
-
end
|
|
54
|
+
.flat_map { |x| x.fetch(Hyrax.config.id_field, []) }
|
|
57
55
|
end
|
|
58
56
|
|
|
59
57
|
def presenter_factory_arguments
|
|
@@ -154,9 +154,9 @@ module Hyrax
|
|
|
154
154
|
def grouped_presenters(filtered_by: nil, except: nil)
|
|
155
155
|
# TODO: we probably need to retain collection_presenters (as parent_presenters)
|
|
156
156
|
# and join this with member_of_collection_presenters
|
|
157
|
-
grouped = member_of_collection_presenters.group_by(&:model_name).transform_keys
|
|
158
|
-
grouped.select! { |obj| obj.
|
|
159
|
-
grouped.except
|
|
157
|
+
grouped = member_of_collection_presenters.group_by(&:model_name).transform_keys(&:human)
|
|
158
|
+
grouped.select! { |obj| obj.casecmp(filtered_by).zero? } unless filtered_by.nil?
|
|
159
|
+
grouped.reject! { |obj| except.map(&:downcase).include? obj.downcase } unless except.nil?
|
|
160
160
|
grouped
|
|
161
161
|
end
|
|
162
162
|
|
|
@@ -200,13 +200,14 @@ module Hyrax
|
|
|
200
200
|
|
|
201
201
|
private
|
|
202
202
|
|
|
203
|
+
##
|
|
204
|
+
# Returns the identifier used by ACLs to identify agents.
|
|
205
|
+
#
|
|
206
|
+
# This defaults to the `:agent_key`, but if that method doesn’t exist,
|
|
207
|
+
# `:user_key` will be used as a fallback.
|
|
203
208
|
def id_for(agent:)
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
"#{Hyrax::Group.name_prefix}#{agent.name}"
|
|
207
|
-
else
|
|
208
|
-
agent.user_key.to_s
|
|
209
|
-
end
|
|
209
|
+
key = agent.try(:agent_key) || agent.user_key
|
|
210
|
+
key.to_s
|
|
210
211
|
end
|
|
211
212
|
end
|
|
212
213
|
|
|
@@ -60,7 +60,7 @@ module Hyrax
|
|
|
60
60
|
object = ActiveFedora::Base.find(id)
|
|
61
61
|
parent_ids = object.try(:member_of_collection_ids) || []
|
|
62
62
|
|
|
63
|
-
#
|
|
63
|
+
# NOTE: we do not yield when the object has parents. Calling the nested indexer for the
|
|
64
64
|
# top id will reindex all descendants as well.
|
|
65
65
|
if object.try(:use_nested_reindexing?)
|
|
66
66
|
yield(id, parent_ids) if parent_ids.empty?
|
|
@@ -119,11 +119,11 @@ module Hyrax
|
|
|
119
119
|
# @yield Samvera::NestingIndexer::Documents::IndexDocument
|
|
120
120
|
#
|
|
121
121
|
# @return [void]
|
|
122
|
-
def self.each_child_document_of(document:, extent:, &block)
|
|
122
|
+
def self.each_child_document_of(document:, extent:, &block) # rubocop:disable Lint/UnusedMethodArgument
|
|
123
123
|
raw_child_solr_documents_of(parent_document: document).each do |solr_document|
|
|
124
124
|
child_document = coerce_solr_document_to_index_document(original_solr_document: solr_document, id: solr_document.fetch('id'))
|
|
125
125
|
# during light reindexing, we want to reindex the child only if fields aren't already there
|
|
126
|
-
|
|
126
|
+
yield(child_document) if full_reindex?(extent: extent) || child_document.pathnames.empty?
|
|
127
127
|
end
|
|
128
128
|
end
|
|
129
129
|
|
|
@@ -91,11 +91,9 @@ class Hyrax::Characterization::ValkyrieCharacterizationService
|
|
|
91
91
|
h = {}
|
|
92
92
|
|
|
93
93
|
doc.class.terminology.terms.each_pair do |key, _target|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
next
|
|
98
|
-
end
|
|
94
|
+
h[key] = doc.public_send(key)
|
|
95
|
+
rescue NoMethodError
|
|
96
|
+
next
|
|
99
97
|
end
|
|
100
98
|
|
|
101
99
|
h.compact
|
|
@@ -83,11 +83,9 @@ module Hyrax
|
|
|
83
83
|
def add_members(collection_id:, new_members:, user:)
|
|
84
84
|
messages = []
|
|
85
85
|
new_members.map do |new_member|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
messages += [err.message]
|
|
90
|
-
end
|
|
86
|
+
add_member(collection_id: collection_id, new_member: new_member, user: user)
|
|
87
|
+
rescue Hyrax::SingleMembershipError => err
|
|
88
|
+
messages += [err.message]
|
|
91
89
|
end
|
|
92
90
|
raise Hyrax::SingleMembershipError, messages if messages.present?
|
|
93
91
|
end
|
|
@@ -5,6 +5,17 @@ module Hyrax
|
|
|
5
5
|
##
|
|
6
6
|
# Listens for events related to {Hyrax::FileMetadata}
|
|
7
7
|
class FileMetadataListener
|
|
8
|
+
##
|
|
9
|
+
# Called when 'file.characterized' event is published;
|
|
10
|
+
# allows post-characterization handling, like derivatives generation.
|
|
11
|
+
#
|
|
12
|
+
# @param [Dry::Events::Event] event
|
|
13
|
+
# @return [void]
|
|
14
|
+
def on_file_characterized(event)
|
|
15
|
+
CreateDerivativesJob
|
|
16
|
+
.perform_later(event[:file_set], event[:file_id], event[:path_hint])
|
|
17
|
+
end
|
|
18
|
+
|
|
8
19
|
##
|
|
9
20
|
# Called when 'file.metadata.updated' event is published; reindexes a
|
|
10
21
|
# {Hyrax::FileSet} when a file claiming to be its `pcdm_use:OriginalFile`
|
|
@@ -13,15 +13,13 @@ module Hyrax
|
|
|
13
13
|
return if event[:object].is_a?(ActiveFedora::Base) # handled by legacy code
|
|
14
14
|
|
|
15
15
|
Hyrax.custom_queries.find_child_file_sets(resource: event[:object]).each do |file_set|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
'This member may now be orphaned.'
|
|
24
|
-
end
|
|
16
|
+
Hyrax.persister.delete(resource: file_set)
|
|
17
|
+
Hyrax.publisher
|
|
18
|
+
.publish('object.deleted', object: file_set, id: file_set.id, user: event[:user])
|
|
19
|
+
rescue StandardError # we don't uncaught errors looping filesets
|
|
20
|
+
Hyrax.logger.warn "Failed to delete #{file_set.class}:#{file_set.id} " \
|
|
21
|
+
"during cleanup for resource: #{event[:object]}. " \
|
|
22
|
+
'This member may now be orphaned.'
|
|
25
23
|
end
|
|
26
24
|
end
|
|
27
25
|
|
|
@@ -33,15 +31,13 @@ module Hyrax
|
|
|
33
31
|
return if event[:collection].is_a?(ActiveFedora::Base) # handled by legacy code
|
|
34
32
|
|
|
35
33
|
Hyrax.custom_queries.find_members_of(collection: event[:collection]).each do |resource|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"during cleanup for collection: #{event[:collection]}. "
|
|
44
|
-
end
|
|
34
|
+
resource.member_of_collection_ids -= [event[:collection].id]
|
|
35
|
+
Hyrax.persister.save(resource: resource)
|
|
36
|
+
Hyrax.publisher
|
|
37
|
+
.publish('collection.membership.updated', collection: event[:collection], user: event[:user])
|
|
38
|
+
rescue StandardError
|
|
39
|
+
Hyrax.logger.warn "Failed to remove collection reference from #{work.class}:#{work.id} " \
|
|
40
|
+
"during cleanup for collection: #{event[:collection]}. "
|
|
45
41
|
end
|
|
46
42
|
end
|
|
47
43
|
end
|
|
@@ -21,7 +21,9 @@ module Hyrax
|
|
|
21
21
|
# also belong to other collections of the same type.
|
|
22
22
|
#
|
|
23
23
|
# @return [True, String] true if no conflicts; otherwise, an error message string
|
|
24
|
+
# @deprecated Use #check instead; for removal in 4.0.0
|
|
24
25
|
def validate
|
|
26
|
+
Deprecation.warn "#{self.class}##{__method__} is deprecated; use #check instead."
|
|
25
27
|
return true if item.member_of_collection_ids.empty? || item.member_of_collection_ids.count <= 1
|
|
26
28
|
return true unless single_membership_collection_types_exist?
|
|
27
29
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Hyrax
|
|
3
|
+
class ValkyriePersistDerivatives < Hydra::Derivatives::PersistOutputFileService
|
|
4
|
+
# Persists a derivative using the defined Valkyrie storage adapter
|
|
5
|
+
#
|
|
6
|
+
# This Service conforms to the signature of `Hydra::Derivatives::PersistOutputFileService`.
|
|
7
|
+
# This service is a Valkyrized alternative to the default Hydra::Derivatives::PersistOutputFileService.
|
|
8
|
+
# This service will always update existing and does not do versioning of persisted files.
|
|
9
|
+
#
|
|
10
|
+
# to replace the default AF derivative pipeline, set
|
|
11
|
+
# ```
|
|
12
|
+
# Hydra::Derivatives.config.output_file_service = Hyrax::ValkyriePersistDerivatives
|
|
13
|
+
# Hydra::Derivatives.config.source_file_service = Hyrax::LocalFileService
|
|
14
|
+
# ```
|
|
15
|
+
#
|
|
16
|
+
# @param [#read] stream the derivative filestream
|
|
17
|
+
# @param [Hash] directives
|
|
18
|
+
# @option directives [String] :url a url to the file destination
|
|
19
|
+
def self.call(stream, directives)
|
|
20
|
+
filepath = URI(directives.fetch(:url)).path
|
|
21
|
+
fileset_id = fileset_id_from_path(filepath)
|
|
22
|
+
fileset = Hyrax.metadata_adapter.query_service.find_by(id: fileset_id)
|
|
23
|
+
|
|
24
|
+
# Valkyrie storage adapters will typically expect an IO-like object that
|
|
25
|
+
# responds to #path -- here we only have a StringIO, so some
|
|
26
|
+
# transformation is in order
|
|
27
|
+
tmpfile = Tempfile.new(fileset_id, encoding: 'ascii-8bit')
|
|
28
|
+
tmpfile.write stream.read
|
|
29
|
+
|
|
30
|
+
Rails.logger.debug "Uploading thumbnail for FileSet #{fileset_id} as #{filepath}"
|
|
31
|
+
Hyrax.config.derivatives_storage_adapter.upload(
|
|
32
|
+
file: tmpfile,
|
|
33
|
+
original_filename: filepath,
|
|
34
|
+
resource: fileset
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# The filepath will look something like
|
|
39
|
+
# /app/samvera/hyrax-webapp/derivatives/95/93/tv/12/3-thumbnail.jpeg and
|
|
40
|
+
# we want to extract the FileSet id, which in this case would be 9593tv123
|
|
41
|
+
#
|
|
42
|
+
# @param [String] path
|
|
43
|
+
# @return [String]
|
|
44
|
+
def self.fileset_id_from_path(path)
|
|
45
|
+
path.sub(Hyrax.config.derivatives_path.to_s, "")
|
|
46
|
+
.sub(/-[^\/]+\..*$/, "")
|
|
47
|
+
.delete("/")
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Hyrax::ValkyrieUpload
|
|
4
|
+
# @param [IO] io
|
|
5
|
+
# @param [String] filename
|
|
6
|
+
# @param [Hyrax::FileSet] file_set
|
|
7
|
+
# @param [RDF::URI] use
|
|
8
|
+
# @param [User] user
|
|
9
|
+
#
|
|
10
|
+
# @see Hyrax::FileMetadata::Use
|
|
11
|
+
# @return [Hyrax::FileMetadata] the metadata representing the uploaded file
|
|
12
|
+
# rubocop:disable Metrics/MethodLength
|
|
13
|
+
# rubocop:disable Metrics/ParameterLists
|
|
14
|
+
def self.file(
|
|
15
|
+
filename:,
|
|
16
|
+
file_set:,
|
|
17
|
+
io:,
|
|
18
|
+
storage_adapter: Hyrax.storage_adapter,
|
|
19
|
+
use: Hyrax::FileMetadata::Use::ORIGINAL_FILE,
|
|
20
|
+
user: nil
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
streamfile = storage_adapter.upload(
|
|
24
|
+
file: io,
|
|
25
|
+
original_filename: filename,
|
|
26
|
+
resource: file_set,
|
|
27
|
+
use: use
|
|
28
|
+
)
|
|
29
|
+
io.close
|
|
30
|
+
|
|
31
|
+
file_metadata = Hyrax::FileMetadata(streamfile)
|
|
32
|
+
file_metadata.file_set_id = file_set.id
|
|
33
|
+
|
|
34
|
+
case use
|
|
35
|
+
when Hyrax::FileMetadata::Use::ORIGINAL_FILE
|
|
36
|
+
# Set file set label.
|
|
37
|
+
reset_title = file_set.title.first == file_set.label
|
|
38
|
+
# set title to label if that's how it was before this characterization
|
|
39
|
+
file_set.title = file_metadata.original_filename if reset_title
|
|
40
|
+
# always set the label to the original_name
|
|
41
|
+
file_set.label = file_metadata.original_filename
|
|
42
|
+
when Hyrax::FileMetadata::Use::THUMBNAIL
|
|
43
|
+
# TODO: the parent work's thumbnail_id remains incorrect (it's set to the
|
|
44
|
+
# FileSet ID, rather than the ID of this thumbnail FileMetadata; but
|
|
45
|
+
# trying to update the parent attributes here doesn't seem to stick
|
|
46
|
+
file_set.thumbnail_id = file_metadata.id
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
saved_metadata = Hyrax.persister.save(resource: file_metadata)
|
|
50
|
+
Hyrax.publisher.publish("object.file.uploaded", metadata: saved_metadata)
|
|
51
|
+
|
|
52
|
+
add_file_to_file_set(file_set: file_set,
|
|
53
|
+
file_metadata: saved_metadata,
|
|
54
|
+
user: user)
|
|
55
|
+
|
|
56
|
+
Hyrax.publisher.publish('file.metadata.updated', metadata: saved_metadata, user: user)
|
|
57
|
+
|
|
58
|
+
saved_metadata
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# @param [Hyrax::FileSet] file_set the file set to add to
|
|
62
|
+
# @param [Hyrax::FileMetadata] file_metadata the metadata object representing
|
|
63
|
+
# the file to add
|
|
64
|
+
# @param [::User] user the user performing the add
|
|
65
|
+
#
|
|
66
|
+
# @return [Hyrax::FileSet] updated file set
|
|
67
|
+
def self.add_file_to_file_set(file_set:, file_metadata:, user:)
|
|
68
|
+
file_set.file_ids << file_metadata.id
|
|
69
|
+
set_file_use_ids(file_set, file_metadata)
|
|
70
|
+
|
|
71
|
+
Hyrax.persister.save(resource: file_set)
|
|
72
|
+
Hyrax.publisher.publish('object.membership.updated', object: file_set, user: user)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# @api private
|
|
76
|
+
# @param [Hyrax::FileSet] file_set the file set to add to
|
|
77
|
+
# @param [Hyrax::FileMetadata] file_metadata the metadata object representing
|
|
78
|
+
# the file to add
|
|
79
|
+
# @return [void]
|
|
80
|
+
def self.set_file_use_ids(file_set, file_metadata)
|
|
81
|
+
file_metadata.type.each do |type|
|
|
82
|
+
case type
|
|
83
|
+
when Hyrax::FileMetadata::Use::ORIGINAL_FILE
|
|
84
|
+
file_set.original_file_id = file_metadata.id
|
|
85
|
+
when Hyrax::FileMetadata::Use::THUMBNAIL
|
|
86
|
+
file_set.thumbnail_id = file_metadata.id
|
|
87
|
+
when Hyrax::FileMetadata::Use::EXTRACTED_TEXT
|
|
88
|
+
file_set.extracted_text_id = file_metadata.id
|
|
89
|
+
else
|
|
90
|
+
Rails.logger.warn "Unknown file use #{file_metadata.type} specified for #{file_metadata.file_identifier}"
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -128,16 +128,14 @@ module Hyrax
|
|
|
128
128
|
def call
|
|
129
129
|
self.errors = []
|
|
130
130
|
Array.wrap(data.fetch(:workflows)).map do |configuration|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
errors << error
|
|
138
|
-
end
|
|
139
|
-
Sipity::Workflow.find_by(name: configuration[:name])
|
|
131
|
+
find_or_create_from(configuration: configuration)
|
|
132
|
+
rescue InvalidStateRemovalException => e
|
|
133
|
+
e.states.each do |state|
|
|
134
|
+
error = I18n.t('hyrax.workflow.load.state_error', workflow_name: state.workflow.name, state_name: state.name, entity_count: state.entities.count)
|
|
135
|
+
Rails.logger.error(error)
|
|
136
|
+
errors << error
|
|
140
137
|
end
|
|
138
|
+
Sipity::Workflow.find_by(name: configuration[:name])
|
|
141
139
|
end
|
|
142
140
|
end
|
|
143
141
|
|
|
@@ -34,12 +34,10 @@ module Hyrax::Strategies
|
|
|
34
34
|
|
|
35
35
|
def yaml_file
|
|
36
36
|
@yaml_file ||=
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
{}
|
|
42
|
-
end
|
|
37
|
+
if File.exist?(@config_file)
|
|
38
|
+
YAML.load_file(@config_file)
|
|
39
|
+
else
|
|
40
|
+
{}
|
|
43
41
|
end
|
|
44
42
|
end
|
|
45
43
|
end
|
|
@@ -4,21 +4,21 @@ module Hyrax
|
|
|
4
4
|
# Override the directory where uploaded files will be stored.
|
|
5
5
|
# This is a sensible default for uploaders that are meant to be mounted:
|
|
6
6
|
def store_dir
|
|
7
|
-
configured_upload_path
|
|
7
|
+
(configured_upload_path / model.class.to_s.underscore / mounted_as.to_s / model.id.to_s).to_s
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def cache_dir
|
|
11
|
-
configured_cache_path
|
|
11
|
+
(configured_cache_path / model.class.to_s.underscore / mounted_as.to_s / model.id.to_s).to_s
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
private
|
|
15
15
|
|
|
16
16
|
def configured_upload_path
|
|
17
|
-
Hyrax.config.upload_path.call
|
|
17
|
+
Pathname.new(Hyrax.config.upload_path.call)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def configured_cache_path
|
|
21
|
-
Hyrax.config.cache_path.call
|
|
21
|
+
Pathname.new(Hyrax.config.cache_path.call)
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
end
|
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module Hyrax
|
|
3
|
-
|
|
3
|
+
##
|
|
4
|
+
# Validates that the record passes the multiple membership requirements for collections.
|
|
4
5
|
class CollectionMembershipValidator < ActiveModel::Validator
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
##
|
|
7
|
+
# @param multiple_membership_checker
|
|
8
|
+
def initialize(multiple_membership_checker: Hyrax::MultipleMembershipChecker, **options)
|
|
9
|
+
@multiple_membership_checker = multiple_membership_checker
|
|
10
|
+
super(options)
|
|
10
11
|
end
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def validate_multi_membership(record)
|
|
13
|
+
def validate(record)
|
|
15
14
|
# collections-in-collections do not have multi-membership restrictions
|
|
16
15
|
return true if record.is_a? Hyrax::Forms::PcdmCollectionForm
|
|
16
|
+
checker = @multiple_membership_checker.new(item: nil)
|
|
17
|
+
ids = collections_ids(record)
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
errors = Array(checker.check(collection_ids: ids))
|
|
20
|
+
record.errors[:member_of_collection_ids].concat(errors)
|
|
19
21
|
end
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
record.member_of_collection_ids = collections_ids(record)
|
|
23
|
-
record.member_of_collection_ids.uniq!
|
|
24
|
-
end
|
|
23
|
+
private
|
|
25
24
|
|
|
26
25
|
def collections_ids(record)
|
|
27
|
-
collection_ids =
|
|
26
|
+
collection_ids = record.member_of_collection_ids.reject(&:blank?)
|
|
27
|
+
|
|
28
28
|
if record.member_of_collections_attributes.present?
|
|
29
29
|
record.member_of_collections_attributes
|
|
30
30
|
.each do |_k, h|
|
|
@@ -32,6 +32,7 @@ module Hyrax
|
|
|
32
32
|
collection_ids << Valkyrie::ID.new(h["id"])
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
|
+
|
|
35
36
|
collection_ids
|
|
36
37
|
end
|
|
37
38
|
end
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
<% model = document.hydra_model %>
|
|
1
2
|
<div class="search-results-title-row">
|
|
2
|
-
|
|
3
|
+
<% if model == Hyrax::PcdmCollection || model < Hyrax::PcdmCollection %>
|
|
4
|
+
<h3 class="search-result-title"><%= link_to document.title_or_label, [hyrax, document] %></h3>
|
|
5
|
+
<%= Hyrax::CollectionPresenter.new(document, current_ability).collection_type_badge %>
|
|
6
|
+
<% else %>
|
|
7
|
+
<h3 class="search-result-title"><%= link_to document.title_or_label, document %></h3>
|
|
8
|
+
<% end %>
|
|
3
9
|
</div>
|
|
10
|
+
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
<% model = document.hydra_model %>
|
|
1
2
|
<div class="col-md-2">
|
|
2
|
-
<
|
|
3
|
-
<%= render_thumbnail_tag document %>
|
|
4
|
-
|
|
3
|
+
<% if model == Hyrax::PcdmCollection || model < Hyrax::PcdmCollection %>
|
|
4
|
+
<%= render_thumbnail_tag document, {}, suppress_link: true %>
|
|
5
|
+
<% else %>
|
|
6
|
+
<div class="list-thumbnail">
|
|
7
|
+
<%= render_thumbnail_tag document %>
|
|
8
|
+
</div>
|
|
9
|
+
<% end %>
|
|
5
10
|
</div>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<%= f.input key,
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
as: :multi_value,
|
|
3
|
+
input_html: {
|
|
4
|
+
class: 'form-control',
|
|
5
|
+
data: { 'autocomplete-url' => "/authorities/search/geonames",
|
|
6
|
+
'autocomplete' => key }
|
|
7
|
+
},
|
|
8
|
+
required: f.object.required?(key) %>
|