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
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'rails/generators'
|
|
3
|
+
require 'rails/generators/model_helpers'
|
|
4
|
+
|
|
5
|
+
class Hyrax::CollectionResourceGenerator < Rails::Generators::NamedBase # rubocop:disable Metrics/ClassLength
|
|
6
|
+
# ActiveSupport can interpret models as plural which causes
|
|
7
|
+
# counter-intuitive route paths. Pull in ModelHelpers from
|
|
8
|
+
# Rails which warns users about pluralization when generating
|
|
9
|
+
# new models or scaffolds.
|
|
10
|
+
include Rails::Generators::ModelHelpers
|
|
11
|
+
|
|
12
|
+
source_root File.expand_path('../templates', __FILE__)
|
|
13
|
+
|
|
14
|
+
argument :with_basic_metadata, type: :string, default: "", banner: 'with_basic_metadata'
|
|
15
|
+
|
|
16
|
+
desc 'This generator makes the following changes to your application:
|
|
17
|
+
1. Creates a collection model and model spec, optionally including basic metadata.
|
|
18
|
+
2. Creates a collection form and spec.
|
|
19
|
+
3. Creates a collection indexer and spec.
|
|
20
|
+
4. Creates a collection metadata config.
|
|
21
|
+
5. Sets this to be the collection class.
|
|
22
|
+
'
|
|
23
|
+
|
|
24
|
+
def self.exit_on_failure?
|
|
25
|
+
true
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def validate_name
|
|
29
|
+
return unless name.strip.casecmp("collection").zero?
|
|
30
|
+
raise Thor::MalformattedArgumentError,
|
|
31
|
+
set_color("Error: A collection resource with the name '#{name}' would cause name-space clashes. "\
|
|
32
|
+
"Please use a different name.", :red)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def banner
|
|
36
|
+
if revoking?
|
|
37
|
+
say_status("info", "DESTROYING VALKYRIE COLLECTION MODEL: #{class_name}", :blue)
|
|
38
|
+
else
|
|
39
|
+
say_status("info", "GENERATING VALKYRIE COLLECTION MODEL: #{class_name}", :blue)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def create_metadata_config
|
|
44
|
+
template('collection_metadata.yaml', File.join('config/metadata/', "#{file_name}.yaml"))
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def create_model
|
|
48
|
+
filepath = File.join('app/models', "#{file_name}.rb")
|
|
49
|
+
template('collection.rb.erb', filepath)
|
|
50
|
+
return unless include_basic_metadata?
|
|
51
|
+
inject_into_file filepath, before: /include Hyrax::Schema/ do
|
|
52
|
+
"include Hyrax::Schema(:basic_metadata)\n "
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def create_model_spec
|
|
57
|
+
return unless rspec_installed?
|
|
58
|
+
filepath = File.join('spec/models/', "#{file_name}_spec.rb")
|
|
59
|
+
template('collection_spec.rb.erb', filepath)
|
|
60
|
+
|
|
61
|
+
return unless include_basic_metadata?
|
|
62
|
+
inject_into_file filepath, after: /it_behaves_like 'a Hyrax::PcdmCollection'/ do
|
|
63
|
+
"\n it_behaves_like 'a model with basic metadata'"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def create_form
|
|
68
|
+
filepath = File.join('app/forms/', "#{file_name}_form.rb")
|
|
69
|
+
template('collection_form.rb.erb', filepath)
|
|
70
|
+
return unless include_basic_metadata?
|
|
71
|
+
inject_into_file filepath, before: /include Hyrax::FormFields/ do
|
|
72
|
+
"include Hyrax::FormFields(:basic_metadata)\n "
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# @todo If shared specs are expanded to test for basic metadata, inject calling that test here.
|
|
77
|
+
def create_form_spec
|
|
78
|
+
return unless rspec_installed?
|
|
79
|
+
template('collection_form_spec.rb.erb', File.join('spec/forms/', "#{file_name}_form_spec.rb"))
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def create_indexer
|
|
83
|
+
filepath = File.join('app/indexers/', "#{file_name}_indexer.rb")
|
|
84
|
+
template('collection_indexer.rb.erb', filepath)
|
|
85
|
+
return unless include_basic_metadata?
|
|
86
|
+
inject_into_file filepath, before: /include Hyrax::Indexer/ do
|
|
87
|
+
"include Hyrax::Indexer(:basic_metadata)\n "
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def create_indexer_spec
|
|
92
|
+
return unless rspec_installed?
|
|
93
|
+
filepath = File.join('spec/indexers/', "#{file_name}_indexer_spec.rb")
|
|
94
|
+
template('collection_indexer_spec.rb.erb', filepath)
|
|
95
|
+
|
|
96
|
+
return unless include_basic_metadata?
|
|
97
|
+
inject_into_file filepath, after: /it_behaves_like 'a Hyrax::Resource indexer'/ do
|
|
98
|
+
"\n it_behaves_like 'a Basic metadata indexer'"
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Inserts after the last registered work, or at the top of the config block
|
|
103
|
+
def set_as_the_collection_class
|
|
104
|
+
config = 'config/initializers/hyrax.rb'
|
|
105
|
+
lastmatch = nil
|
|
106
|
+
in_root do
|
|
107
|
+
File.open(config).each_line do |line|
|
|
108
|
+
lastmatch = line if line.match?(/config.collection_model = /)
|
|
109
|
+
end
|
|
110
|
+
content = " # Injected via `rails g hyrax:collection_resource #{class_name}`\n" \
|
|
111
|
+
" config.collection_model = '#{class_name}'\n"
|
|
112
|
+
|
|
113
|
+
anchor = lastmatch || "Hyrax.config do |config|\n"
|
|
114
|
+
inject_into_file config, after: anchor do
|
|
115
|
+
content
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
private
|
|
121
|
+
|
|
122
|
+
def include_basic_metadata?
|
|
123
|
+
with_basic_metadata.present? && with_basic_metadata == "with_basic_metadata"
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def rspec_installed?
|
|
127
|
+
defined?(RSpec) && defined?(RSpec::Rails)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def revoking?
|
|
131
|
+
behavior == :revoke
|
|
132
|
+
end
|
|
133
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Generated via
|
|
4
|
+
# `rails generate hyrax:collection_resource <%= class_name %>`
|
|
5
|
+
class <%= class_name %> < Hyrax::PcdmCollection
|
|
6
|
+
# @note Do not directly update `basic_metadata.yaml`. It is also used by works.
|
|
7
|
+
#
|
|
8
|
+
# To change metadata for collections
|
|
9
|
+
# * extend by adding fields to `/config/metadata/<%= file_name %>.yaml`
|
|
10
|
+
# * remove all basic metadata
|
|
11
|
+
# * if you generated `with_basic_metadata` and now don't want any basic metadata,
|
|
12
|
+
# comment out or delete the schema include statement for `:basic_metadata`
|
|
13
|
+
# * update form and indexer classes to also remove the `:basic_metadata` schema include
|
|
14
|
+
# * remove some basic metadata
|
|
15
|
+
# * comment out or delete the schema include statement for `:basic_metadata`
|
|
16
|
+
# * update form and indexer classes to also remove the `:basic_metadata` schema include
|
|
17
|
+
# * copy fields you want to keep from `/config/metadata/basic_metadata.yaml`
|
|
18
|
+
# to `/config/metadata/<%= file_name %>.yaml`
|
|
19
|
+
# * override some basic metadata
|
|
20
|
+
# * fields are not allowed to repeat, so to override any basic metadata, you
|
|
21
|
+
# must first comment out or delete the schema include statement for `:basic_metadata`
|
|
22
|
+
# * update form and indexer classes to also remove the `:basic_metadata` schema include
|
|
23
|
+
# * copy all fields you want to keep unchanged or to override from `/config/metadata/basic_metadata.yaml`
|
|
24
|
+
# to `/config/metadata/<%= file_name %>.yaml`
|
|
25
|
+
# * update them in `config/metadata/<%= file_name %>.yaml to have the desired
|
|
26
|
+
# characteristics
|
|
27
|
+
#
|
|
28
|
+
# Alternative:
|
|
29
|
+
# * comment out or delete schema include statements
|
|
30
|
+
# * add Valkyrie attributes to this class
|
|
31
|
+
# * update form and indexer to process the attributes
|
|
32
|
+
#
|
|
33
|
+
include Hyrax::Schema(:<%= file_name %>)
|
|
34
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Generated via
|
|
4
|
+
# `rails generate hyrax:collection_resource <%= class_name %>`
|
|
5
|
+
require 'rails_helper'
|
|
6
|
+
require 'valkyrie/specs/shared_specs'
|
|
7
|
+
|
|
8
|
+
RSpec.describe <%= class_name %>Form do
|
|
9
|
+
let(:change_set) { described_class.new(resource) }
|
|
10
|
+
let(:resource) { <%= class_name %>.new }
|
|
11
|
+
|
|
12
|
+
it_behaves_like 'a Valkyrie::ChangeSet'
|
|
13
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Generated via
|
|
4
|
+
# `rails generate hyrax:collection_resource <%= class_name %>`
|
|
5
|
+
require 'rails_helper'
|
|
6
|
+
require 'hyrax/specs/shared_specs/indexers'
|
|
7
|
+
|
|
8
|
+
RSpec.describe <%= class_name %>Indexer do
|
|
9
|
+
let(:indexer_class) { described_class }
|
|
10
|
+
let(:resource) { <%= class_name %>.new }
|
|
11
|
+
|
|
12
|
+
it_behaves_like 'a Hyrax::Resource indexer'
|
|
13
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Simple yaml config-driven schema which is used to define model attributes,
|
|
2
|
+
# index key names, and form properties.
|
|
3
|
+
#
|
|
4
|
+
# Attributes must have a type but all other configuration options are optional.
|
|
5
|
+
#
|
|
6
|
+
# attributes:
|
|
7
|
+
# attribute_name:
|
|
8
|
+
# type: string
|
|
9
|
+
# multiple: false
|
|
10
|
+
# index_keys:
|
|
11
|
+
# - "attribute_name_sim"
|
|
12
|
+
# form:
|
|
13
|
+
# required: true
|
|
14
|
+
# primary: true
|
|
15
|
+
# multiple: false
|
|
16
|
+
#
|
|
17
|
+
# @see config/metadata/basic_metadata.yaml for an example configuration
|
|
18
|
+
#
|
|
19
|
+
# Generated via
|
|
20
|
+
# `rails generate hyrax:collection_resource <%= class_name %>`
|
|
21
|
+
|
|
22
|
+
attributes: {}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Generated via
|
|
4
|
+
# `rails generate hyrax:collection_resource <%= class_name %>`
|
|
5
|
+
require 'rails_helper'
|
|
6
|
+
require 'hyrax/specs/shared_specs/hydra_works'
|
|
7
|
+
|
|
8
|
+
RSpec.describe <%= class_name %> do
|
|
9
|
+
subject(:collection) { described_class.new }
|
|
10
|
+
|
|
11
|
+
it_behaves_like 'a Hyrax::PcdmCollection'
|
|
12
|
+
end
|
|
@@ -35,6 +35,15 @@ module Hyrax
|
|
|
35
35
|
18. Generates RIIIF image server implementation
|
|
36
36
|
"""
|
|
37
37
|
|
|
38
|
+
# browse-everything 1.2.0 is not compatible with Ruby 2.5
|
|
39
|
+
def pin_browse_everything
|
|
40
|
+
return unless Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.6')
|
|
41
|
+
gem 'browse-everything', '~> 1.1.2'
|
|
42
|
+
Bundler.with_clean_env do
|
|
43
|
+
run "bundle update browse-everything"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
38
47
|
def run_required_generators
|
|
39
48
|
say_status('info', '[Hyrax] GENERATING BLACKLIGHT', :blue)
|
|
40
49
|
generate 'blacklight:install --devise'
|
data/lib/hyrax/configuration.rb
CHANGED
|
@@ -427,6 +427,18 @@ module Hyrax
|
|
|
427
427
|
@branding_storage_adapter = Valkyrie::StorageAdapter.find(adapter.to_sym)
|
|
428
428
|
end
|
|
429
429
|
|
|
430
|
+
##
|
|
431
|
+
# @return [Valkyrie::StorageAdapter]
|
|
432
|
+
def derivatives_storage_adapter
|
|
433
|
+
@derivatives_storage_adapter ||= Valkyrie::StorageAdapter.find(:derivatives_disk)
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
##
|
|
437
|
+
# @param [#to_sym] adapter
|
|
438
|
+
def derivatives_storage_adapter=(adapter)
|
|
439
|
+
@derivatives_storage_adapter = Valkyrie::StorageAdapter.find(adapter.to_sym)
|
|
440
|
+
end
|
|
441
|
+
|
|
430
442
|
##
|
|
431
443
|
# @return [#save, #save_all, #delete, #wipe!] an indexing adapter
|
|
432
444
|
def index_adapter
|
data/lib/hyrax/publisher.rb
CHANGED
|
@@ -119,6 +119,10 @@ module Hyrax
|
|
|
119
119
|
# unique id), AND a `:user` (the ::User responsible for the update).
|
|
120
120
|
register_event('collection.membership.updated')
|
|
121
121
|
|
|
122
|
+
# @since 3.5.0
|
|
123
|
+
# @macro a_registered_event
|
|
124
|
+
register_event('file.characterized')
|
|
125
|
+
|
|
122
126
|
# @since 3.3.0
|
|
123
127
|
# @macro a_registered_event
|
|
124
128
|
register_event('file.downloaded')
|
|
@@ -135,7 +135,6 @@ RSpec.shared_examples 'a Hyrax::PcdmCollection' do
|
|
|
135
135
|
|
|
136
136
|
it_behaves_like 'a Hyrax::Resource'
|
|
137
137
|
it_behaves_like 'a model with core metadata'
|
|
138
|
-
it_behaves_like 'a model with basic metadata'
|
|
139
138
|
it_behaves_like 'has members'
|
|
140
139
|
|
|
141
140
|
describe '#collection_type_gid' do
|
|
@@ -42,6 +42,8 @@ module Hyrax
|
|
|
42
42
|
require 'hyrax/transactions/steps/remove_file_set_from_work'
|
|
43
43
|
require 'hyrax/transactions/steps/save'
|
|
44
44
|
require 'hyrax/transactions/steps/save_access_control'
|
|
45
|
+
require 'hyrax/transactions/steps/save_collection_banner'
|
|
46
|
+
require 'hyrax/transactions/steps/save_collection_logo'
|
|
45
47
|
require 'hyrax/transactions/steps/set_default_admin_set'
|
|
46
48
|
require 'hyrax/transactions/steps/set_modified_date'
|
|
47
49
|
require 'hyrax/transactions/steps/set_uploaded_date_unless_present'
|
|
@@ -195,6 +197,14 @@ module Hyrax
|
|
|
195
197
|
ops.register 'save_acl' do
|
|
196
198
|
Steps::SaveAccessControl.new
|
|
197
199
|
end
|
|
200
|
+
|
|
201
|
+
ops.register 'save_collection_banner' do
|
|
202
|
+
Steps::SaveCollectionBanner.new
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
ops.register 'save_collection_logo' do
|
|
206
|
+
Steps::SaveCollectionLogo.new
|
|
207
|
+
end
|
|
198
208
|
end
|
|
199
209
|
|
|
200
210
|
namespace 'work_resource' do |ops| # Hyrax::Work resource
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Hyrax
|
|
3
|
+
module Transactions
|
|
4
|
+
module Steps
|
|
5
|
+
##
|
|
6
|
+
# Adds banner info via `ChangeSet`.
|
|
7
|
+
#
|
|
8
|
+
# During the update collection process this step is called to update the file
|
|
9
|
+
# to be used as a the banner for the collection.
|
|
10
|
+
#
|
|
11
|
+
class SaveCollectionBanner
|
|
12
|
+
include Dry::Transaction::Operation
|
|
13
|
+
|
|
14
|
+
##
|
|
15
|
+
# @param [Hyrax::ChangeSet] change_set
|
|
16
|
+
# @param [Array<Integer>] update_banner_file_ids
|
|
17
|
+
# @param [Boolean] banner_unchanged_indicator
|
|
18
|
+
#
|
|
19
|
+
# @return [Dry::Monads::Result] `Failure` if the banner info fails to save;
|
|
20
|
+
# `Success(input)`, otherwise.
|
|
21
|
+
def call(collection_resource, update_banner_file_ids: nil, banner_unchanged_indicator: true)
|
|
22
|
+
return Success(collection_resource) if ActiveModel::Type::Boolean.new.cast(banner_unchanged_indicator)
|
|
23
|
+
collection_id = collection_resource.id.to_s
|
|
24
|
+
process_banner_input(collection_id: collection_id, update_banner_file_ids: update_banner_file_ids)
|
|
25
|
+
Success(collection_resource)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def process_banner_input(collection_id:, update_banner_file_ids:)
|
|
31
|
+
remove_banner(collection_id: collection_id)
|
|
32
|
+
add_new_banner(collection_id: collection_id, uploaded_file_ids: update_banner_file_ids) if update_banner_file_ids
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def remove_banner(collection_id:)
|
|
36
|
+
banner_info = CollectionBrandingInfo.where(collection_id: collection_id).where(role: "banner")
|
|
37
|
+
banner_info&.delete_all
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def add_new_banner(collection_id:, uploaded_file_ids:)
|
|
41
|
+
f = uploaded_files(uploaded_file_ids).first
|
|
42
|
+
banner_info = CollectionBrandingInfo.new(
|
|
43
|
+
collection_id: collection_id,
|
|
44
|
+
filename: File.split(f.file_url).last,
|
|
45
|
+
role: "banner",
|
|
46
|
+
alt_txt: "",
|
|
47
|
+
target_url: ""
|
|
48
|
+
)
|
|
49
|
+
banner_info.save f.file_url
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def uploaded_files(uploaded_file_ids)
|
|
53
|
+
return [] if uploaded_file_ids.empty?
|
|
54
|
+
UploadedFile.find(uploaded_file_ids)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Hyrax
|
|
3
|
+
module Transactions
|
|
4
|
+
module Steps
|
|
5
|
+
##
|
|
6
|
+
# Adds logo info via `ChangeSet`.
|
|
7
|
+
#
|
|
8
|
+
# During the update collection process this step is called to update the file(s)
|
|
9
|
+
# to be used as logo(s) for the collection.
|
|
10
|
+
#
|
|
11
|
+
class SaveCollectionLogo
|
|
12
|
+
include Dry::Transaction::Operation
|
|
13
|
+
|
|
14
|
+
##
|
|
15
|
+
# @param [Hyrax::ChangeSet] change_set
|
|
16
|
+
# @param [Array<#Integer>] update_logo_file_ids
|
|
17
|
+
# @param [Array<String>] alttext_values
|
|
18
|
+
# @param [Array<String>] linkurl_values
|
|
19
|
+
#
|
|
20
|
+
# @return [Dry::Monads::Result] `Failure` if the work fails to save;
|
|
21
|
+
# `Success(input)`, otherwise.
|
|
22
|
+
def call(collection_resource, update_logo_file_ids: nil, alttext_values: nil, linkurl_values: nil)
|
|
23
|
+
collection_id = collection_resource.id.to_s
|
|
24
|
+
process_logo_input(collection_id: collection_id, update_logo_file_ids: update_logo_file_ids, alttext_values: alttext_values, linkurl_values: linkurl_values)
|
|
25
|
+
Success(collection_resource)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
def process_logo_input(collection_id:, update_logo_file_ids:, alttext_values:, linkurl_values:)
|
|
31
|
+
uploaded_file_ids = update_logo_file_ids
|
|
32
|
+
public_files = []
|
|
33
|
+
|
|
34
|
+
if uploaded_file_ids.nil?
|
|
35
|
+
# all logo files were removed, so delete all files previously uploaded
|
|
36
|
+
remove_redundant_files(collection_id: collection_id, public_files: public_files)
|
|
37
|
+
return
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
public_files = process_logo_records(collection_id: collection_id, uploaded_file_ids: uploaded_file_ids, alttext_values: alttext_values, linkurl_values: linkurl_values)
|
|
41
|
+
remove_redundant_files(collection_id: collection_id, public_files: public_files)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def process_logo_records(collection_id:, uploaded_file_ids:, alttext_values:, linkurl_values:)
|
|
45
|
+
public_files = []
|
|
46
|
+
uploaded_file_ids.each_with_index do |ufi, i|
|
|
47
|
+
# If the user has chosen a new logo, the ufi will be an integer
|
|
48
|
+
# If the logo was previously chosen, the ufi will be a path
|
|
49
|
+
# If it is a path, update the rec, else create a new rec
|
|
50
|
+
if !ufi.match(/\D/).nil?
|
|
51
|
+
update_logo_info(collection_id: collection_id, uploaded_file_id: ufi, alttext: alttext_values[i], linkurl: verify_linkurl(linkurl_values[i]))
|
|
52
|
+
public_files << ufi
|
|
53
|
+
else # brand new one, insert in the database
|
|
54
|
+
logo_info = create_logo_info(collection_id: collection_id, uploaded_file_id: ufi, alttext: alttext_values[i], linkurl: verify_linkurl(linkurl_values[i]))
|
|
55
|
+
public_files << logo_info.local_path
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
public_files
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def update_logo_info(collection_id:, uploaded_file_id:, alttext:, linkurl:)
|
|
62
|
+
logo_info = CollectionBrandingInfo.where(collection_id: collection_id).where(role: "logo").where(local_path: uploaded_file_id.to_s).first
|
|
63
|
+
logo_info.alt_text = alttext
|
|
64
|
+
logo_info.target_url = linkurl
|
|
65
|
+
logo_info.local_path = uploaded_file_id
|
|
66
|
+
logo_info.save(uploaded_file_id, false)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def create_logo_info(collection_id:, uploaded_file_id:, alttext:, linkurl:)
|
|
70
|
+
file = uploaded_files(uploaded_file_id)
|
|
71
|
+
logo_info = CollectionBrandingInfo.new(
|
|
72
|
+
collection_id: collection_id,
|
|
73
|
+
filename: File.split(file.file_url).last,
|
|
74
|
+
role: "logo",
|
|
75
|
+
alt_txt: alttext,
|
|
76
|
+
target_url: linkurl
|
|
77
|
+
)
|
|
78
|
+
logo_info.save file.file_url
|
|
79
|
+
logo_info
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def uploaded_files(uploaded_file_ids)
|
|
83
|
+
return [] if uploaded_file_ids.empty?
|
|
84
|
+
UploadedFile.find(uploaded_file_ids)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def remove_redundant_files(collection_id:, public_files:)
|
|
88
|
+
# remove any public ones that were not included in the selection.
|
|
89
|
+
logos_info = CollectionBrandingInfo.where(collection_id: collection_id).where(role: "logo")
|
|
90
|
+
logos_info.each do |logo_info|
|
|
91
|
+
logo_info.delete(logo_info.local_path) unless public_files.include? logo_info.local_path
|
|
92
|
+
logo_info.destroy unless public_files.include? logo_info.local_path
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Only accept HTTP|HTTPS urls;
|
|
97
|
+
# @return <String> the url
|
|
98
|
+
def verify_linkurl(linkurl)
|
|
99
|
+
url = Loofah.scrub_fragment(linkurl, :prune).to_s
|
|
100
|
+
url if valid_url?(url)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def valid_url?(url)
|
|
104
|
+
(url =~ URI.regexp(['http', 'https']))
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
data/lib/hyrax/version.rb
CHANGED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wings
|
|
4
|
+
class ActiveFedoraConverter
|
|
5
|
+
def self.FileMetadataNode(resource_class) # rubocop:disable Naming/MethodName
|
|
6
|
+
class_cache[resource_class] ||= Class.new(FileMetadataNode) do
|
|
7
|
+
self.valkyrie_class = resource_class
|
|
8
|
+
|
|
9
|
+
# skip reserved attributes, we assume we don't need to translate valkyrie internals
|
|
10
|
+
schema = resource_class.schema.reject do |key|
|
|
11
|
+
resource_class.reserved_attributes.include?(key.name) ||
|
|
12
|
+
key.name == :size
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
Wings::ActiveFedoraConverter.apply_properties(self, schema)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class FileMetadataNode < ActiveFedora::Base
|
|
21
|
+
property :file_set_id, predicate: ::RDF::URI.intern("http://hyrax.samvera.org/ns/wings#file_set_id")
|
|
22
|
+
property :file_identifier, predicate: ::RDF::URI.intern("http://hyrax.samvera.org/ns/wings#file_identifier")
|
|
23
|
+
|
|
24
|
+
class_attribute :valkyrie_class
|
|
25
|
+
|
|
26
|
+
class << self
|
|
27
|
+
def model_name(*)
|
|
28
|
+
Hyrax::Name.new(valkyrie_class)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def to_rdf_representation
|
|
32
|
+
"Wings(#{valkyrie_class})"
|
|
33
|
+
end
|
|
34
|
+
alias inspect to_rdf_representation
|
|
35
|
+
alias to_s inspect
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def indexing_service
|
|
39
|
+
Hyrax::ValkyrieIndexer.for(resource: valkyrie_resource)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def to_solr
|
|
43
|
+
super.tap do |doc|
|
|
44
|
+
doc[:file_identifier_ssim] = file_identifier
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Wings
|
|
4
|
+
class ActiveFedoraConverter
|
|
5
|
+
##
|
|
6
|
+
# Constructs an instance for the given converter. +converter+ must provide
|
|
7
|
+
# an +id+, +resource+, and +active_fedora_class+.
|
|
8
|
+
#
|
|
9
|
+
# This interface allows handling for special cases based on the target
|
|
10
|
+
# class, instance data for +resource+, or the id format. This originated as
|
|
11
|
+
# an extraction of some such special handling from the converter code.
|
|
12
|
+
class InstanceBuilder
|
|
13
|
+
##
|
|
14
|
+
# @!attribute [r] converter
|
|
15
|
+
# @return [#active_fedora_class, #id, #resource]
|
|
16
|
+
# @!attribute [r] resource
|
|
17
|
+
# @return [Valkyrie::Resource]
|
|
18
|
+
attr_reader :converter, :resource
|
|
19
|
+
|
|
20
|
+
##
|
|
21
|
+
# @param [#active_fedora_class, #id, #resource]
|
|
22
|
+
def initialize(converter)
|
|
23
|
+
@converter = converter
|
|
24
|
+
@resource = converter.resource
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
##
|
|
28
|
+
# @return [ActiveFedora::Common]
|
|
29
|
+
def build
|
|
30
|
+
if builds_file_metadata? && !builds_metadata_for_active_fedora_file?
|
|
31
|
+
# convert to a generic/generated FileMetadataNode class with
|
|
32
|
+
# properties matching the source class
|
|
33
|
+
Wings::ActiveFedoraConverter::FileMetadataNode(resource.class)
|
|
34
|
+
.new(file_identifier: Array(resource.file_identifier)
|
|
35
|
+
.map(&:to_s))
|
|
36
|
+
elsif converter.id.present?
|
|
37
|
+
converter.active_fedora_class.find(converter.id)
|
|
38
|
+
else
|
|
39
|
+
converter.active_fedora_class.new
|
|
40
|
+
end
|
|
41
|
+
rescue ActiveFedora::ObjectNotFoundError
|
|
42
|
+
converter.active_fedora_class.new
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
##
|
|
46
|
+
# @return [Boolean]
|
|
47
|
+
def builds_file_metadata?
|
|
48
|
+
resource.try(:file_identifier).present?
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
##
|
|
52
|
+
# @return [Boolean]
|
|
53
|
+
def builds_metadata_for_active_fedora_file?
|
|
54
|
+
return false unless builds_file_metadata?
|
|
55
|
+
|
|
56
|
+
adapter_for_file = begin
|
|
57
|
+
::Valkyrie::StorageAdapter.adapter_for(id: resource.file_identifier)
|
|
58
|
+
rescue ::Valkyrie::StorageAdapter::AdapterNotFoundError => err
|
|
59
|
+
Hyrax.logger.warn "Processing a FileMetadata (id: #{converter.id}) referencing " \
|
|
60
|
+
"a file #{resource.file_identifier}; could not find a " \
|
|
61
|
+
"storage adapter to handle that file.\n\t#{err.message}"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
adapter_for_file.is_a?(::Valkyrie::Storage::Fedora)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require 'wings/converter_value_mapper'
|
|
4
4
|
require 'wings/active_fedora_converter/default_work'
|
|
5
|
+
require 'wings/active_fedora_converter/file_metadata_node'
|
|
6
|
+
require 'wings/active_fedora_converter/instance_builder'
|
|
5
7
|
require 'wings/active_fedora_converter/nested_resource'
|
|
6
8
|
|
|
7
9
|
module Wings
|
|
@@ -100,9 +102,7 @@ module Wings
|
|
|
100
102
|
private
|
|
101
103
|
|
|
102
104
|
def instance
|
|
103
|
-
|
|
104
|
-
rescue ActiveFedora::ObjectNotFoundError
|
|
105
|
-
active_fedora_class.new
|
|
105
|
+
InstanceBuilder.new(self).build
|
|
106
106
|
end
|
|
107
107
|
|
|
108
108
|
def attributes_class
|