hyrax 5.1.0 → 5.2.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.
- checksums.yaml +4 -4
- data/.dassie/Gemfile +1 -1
- data/.dassie/config/application.rb +1 -1
- data/.dassie/config/initializers/devise.rb +1 -0
- data/.dassie/db/schema.rb +110 -109
- data/.github/workflows/lint-build-test.yml +1 -1
- data/.koppie/config/initializers/devise.rb +1 -1
- data/CONTAINERS.md +10 -10
- data/Gemfile +2 -1
- data/app/controllers/concerns/hyrax/valkyrie_downloads_controller_behavior.rb +1 -0
- data/app/controllers/concerns/hyrax/works_controller_behavior.rb +2 -1
- data/app/controllers/hyrax/admin/analytics/work_reports_controller.rb +4 -4
- data/app/controllers/hyrax/file_sets_controller.rb +1 -1
- data/app/helpers/hyrax/hyrax_helper_behavior.rb +2 -2
- data/app/helpers/hyrax/trophy_helper.rb +1 -1
- data/app/jobs/concerns/hyrax/queued_job_behavior.rb +22 -0
- data/app/jobs/hyrax/propagate_change_depositor_job.rb +1 -1
- data/app/jobs/hyrax/queued_delete_job.rb +11 -0
- data/app/jobs/hyrax/queued_indexing_job.rb +11 -0
- data/app/jobs/migrate_files_to_valkyrie_job.rb +33 -21
- data/app/jobs/migrate_sipity_entity_job.rb +21 -0
- data/app/models/concerns/hyrax/ability.rb +4 -2
- data/app/models/concerns/hyrax/solr_document_behavior.rb +5 -2
- data/app/models/hyrax/file_metadata.rb +22 -7
- data/app/services/hyrax/analytics/ga4/base.rb +1 -1
- data/app/services/hyrax/analytics/ga4.rb +5 -1
- data/app/services/hyrax/change_depositor_service.rb +1 -1
- data/app/services/hyrax/characterization/valkyrie_characterization_service.rb +21 -13
- data/app/services/hyrax/custom_queries/find_ids_by_model.rb +31 -6
- data/app/services/hyrax/edit_permissions_service.rb +9 -8
- data/app/services/hyrax/workflow/workflow_factory.rb +3 -3
- data/app/services/migrate_resource_service.rb +1 -1
- data/app/views/_user_util_links.html.erb +2 -1
- data/app/views/hyrax/admin/analytics/collection_reports/_top_collections.html.erb +3 -7
- data/app/views/hyrax/admin/analytics/work_reports/_top_file_set_downloads.html.erb +3 -6
- data/app/views/hyrax/admin/analytics/work_reports/_top_works.html.erb +2 -3
- data/app/views/hyrax/admin/analytics/work_reports/_work_files.html.erb +1 -6
- data/app/views/hyrax/base/_social_media.html.erb +2 -0
- data/app/views/hyrax/dashboard/collections/_show_document_list_menu.html.erb +13 -12
- data/app/views/hyrax/my/_admin_set_action_menu.html.erb +31 -27
- data/app/views/hyrax/my/_collection_action_menu.html.erb +40 -35
- data/app/views/hyrax/my/_work_action_menu.html.erb +23 -22
- data/config/features.rb +50 -40
- data/config/initializers/indexing_adapter_initializer.rb +4 -0
- data/config/initializers/new_framework_defaults_7_2.rb +6 -4
- data/config/initializers/reform_rails_6_1_monkey_patch.rb +29 -0
- data/config/metadata/core_metadata.yaml +1 -0
- data/docker-compose-dassie.yml +4 -4
- data/documentation/developing-your-hyrax-based-app.md +2 -2
- data/hyrax.gemspec +2 -2
- data/lib/freyja/persister.rb +11 -4
- data/lib/hyrax/configuration.rb +22 -7
- data/lib/hyrax/controlled_vocabulary/importer/language.rb +5 -1
- data/lib/hyrax/transactions/steps/add_file_sets.rb +2 -1
- data/lib/hyrax/version.rb +1 -1
- data/lib/hyrax.rb +1 -0
- data/lib/valkyrie/indexing/redis_queue/indexing_adapter.rb +144 -0
- data/lib/wings/valkyrie/query_service.rb +3 -4
- data/template.rb +1 -1
- metadata +20 -12
- data/.github/workflows/main.yml +0 -17
data/CONTAINERS.md
CHANGED
@@ -53,7 +53,7 @@ With `docker compose up` running, any changes you make to your cloned Hyrax code
|
|
53
53
|
Any changes you make to Hyrax should be tested. You can run the full test suite using the following command:
|
54
54
|
|
55
55
|
```sh
|
56
|
-
docker compose exec -w /app/samvera/hyrax-engine
|
56
|
+
docker compose exec -w /app/samvera/hyrax-engine web sh -c "bundle exec rspec"
|
57
57
|
```
|
58
58
|
|
59
59
|
Let's break down the above command:
|
@@ -63,8 +63,8 @@ Let's break down the above command:
|
|
63
63
|
<dd>Tell docker to run the following:</dd>
|
64
64
|
<dt><code>-w /app/samvera/hyrax-engine</code></dt>
|
65
65
|
<dd>In the working directory "/app/samvera/hyrax-engine" (e.g. your cloned Hyrax repository)</dd>
|
66
|
-
<dt><code>
|
67
|
-
<dd>of the container named "
|
66
|
+
<dt><code>web</code></dt>
|
67
|
+
<dd>of the container named "web"</dd>
|
68
68
|
<dt><code>sh -c</code>
|
69
69
|
<dd>run the following shell script</dd>
|
70
70
|
<dt><code>"bundle exec rspec"</code></dt>
|
@@ -73,26 +73,26 @@ Let's break down the above command:
|
|
73
73
|
|
74
74
|
_**Note:**_ The `bundle exec rspec` portion of the command runs the whole test suite. See the [rspec command documentation](https://github.com/rspec/rspec-core#the-rspec-command) for how to refine your test runs.
|
75
75
|
|
76
|
-
#### The Docker Container Named "
|
76
|
+
#### The Docker Container Named "web"
|
77
77
|
|
78
78
|
As a developer, you may need to run commands against the Hyrax-based application and/or the Hyrax engine. Examples
|
79
79
|
of those commands are `rails db:migrate` and `rspec`. You would run `rails db:migrate` on the Hyrax-based
|
80
80
|
application, and `rspec` on the Hyrax engine.
|
81
81
|
|
82
|
-
In the engine development `
|
82
|
+
In the engine development `web` container, the `.dassie` test Hyrax-based application is setup as a docker
|
83
83
|
bind mount to `/app/samvera/hyrax-webapp`, and your local development copy of Hyrax (eg. the clone [samvera/hyrax](https://github.com/samvera/hyrax)) is bound to
|
84
84
|
`/app/samvera/hyrax-engine`. Those directories are defined as part of the [Dockerfile](Dockerfile) configuration.
|
85
85
|
.
|
86
86
|
What does this structure mean? Let's look at an example. The following command will list the rake tasks for the Hyrax-based application running in Docker:
|
87
87
|
|
88
88
|
```sh
|
89
|
-
docker compose exec -w /app/samvera/hyrax-webapp
|
89
|
+
docker compose exec -w /app/samvera/hyrax-webapp web sh -c "bundle exec rake -T"
|
90
90
|
```
|
91
91
|
|
92
92
|
And this command lists the rake tasks for the Hyrax engine that is in Docker:
|
93
93
|
|
94
94
|
```sh
|
95
|
-
docker compose exec -w /app/samvera/hyrax-engine
|
95
|
+
docker compose exec -w /app/samvera/hyrax-engine web sh -c "bundle exec rake -T"
|
96
96
|
```
|
97
97
|
|
98
98
|
In the two examples, note the difference in the `-w` switch. In the first case, it's referencing the Hyrax-based application. In the latter case, it's referencing the Hyrax engine.
|
@@ -165,13 +165,13 @@ Currently Koppie should not be used for running specs. See [Code Changes and Tes
|
|
165
165
|
|
166
166
|
```sh
|
167
167
|
docker compose -f docker-compose-koppie.yml up
|
168
|
-
docker compose -f docker-compose-koppie.yml exec
|
168
|
+
docker compose -f docker-compose-koppie.yml exec web bundle exec rails c
|
169
169
|
```
|
170
170
|
#### Troubleshooting Koppie
|
171
171
|
|
172
172
|
If the postgres service logs show permissions errors, there may be old data from alternate versions of the postgres image. The old data volumes can deleted by using `docker compose -f docker-compose-koppie.yml down -v`
|
173
173
|
|
174
|
-
Errors such as `exec /app/samvera/hyrax-entrypoint.sh: no such file or directory` in the
|
174
|
+
Errors such as `exec /app/samvera/hyrax-entrypoint.sh: no such file or directory` in the web, sidekiq and db_migrate services may indicate an outdated cached hyrax-base image layer was used to build the koppie image. Try `docker compose -f docker-compose-koppie.yml build --no-cache` to rebuild all the image layers.
|
175
175
|
|
176
176
|
It was also seen on a Windows 10 host and was resolved by using the git `--core.autocrlf` option when cloning the repo.
|
177
177
|
|
@@ -217,7 +217,7 @@ Currently Sirenia should not be used for running specs. See [Code Changes and Te
|
|
217
217
|
|
218
218
|
```sh
|
219
219
|
docker compose -f docker-compose-sirenia.yml up
|
220
|
-
docker compose -f docker-compose-sirenia.yml exec
|
220
|
+
docker compose -f docker-compose-sirenia.yml exec web bundle exec rails c
|
221
221
|
```
|
222
222
|
|
223
223
|
### Maintaining
|
data/Gemfile
CHANGED
@@ -102,6 +102,7 @@ module Hyrax
|
|
102
102
|
def find_file_metadata(file_set:, use: :original_file, mime_type: nil)
|
103
103
|
if mime_type.nil?
|
104
104
|
use = :thumbnail_file if use == :thumbnail
|
105
|
+
use = :original_file unless Hyrax::FileMetadata::Use.keys.include?(use)
|
105
106
|
use = Hyrax::FileMetadata::Use.uri_for(use: use)
|
106
107
|
results = Hyrax.custom_queries.find_many_file_metadata_by_use(resource: file_set, use: use)
|
107
108
|
else
|
@@ -359,8 +359,9 @@ module Hyrax
|
|
359
359
|
# intersection, we get the files they added via BrowseEverything
|
360
360
|
# that they have not removed from the upload widget.
|
361
361
|
uploaded_files = params.fetch(:uploaded_files, [])
|
362
|
+
params.permit(selected_files: [:expires, :file_name, :url])
|
362
363
|
selected_files = params.fetch(:selected_files, {}).values
|
363
|
-
|
364
|
+
|
364
365
|
browse_everything_urls = uploaded_files &
|
365
366
|
selected_files.map { |f| f[:url] }
|
366
367
|
|
@@ -14,9 +14,9 @@ module Hyrax
|
|
14
14
|
@works_count = @accessible_works.count
|
15
15
|
@top_works = paginate(top_works_list, rows: 10)
|
16
16
|
@top_file_set_downloads = paginate(top_files_list, rows: 10)
|
17
|
-
|
18
|
-
@pageviews = Hyrax::Analytics.daily_events('work-view'),
|
19
|
-
|
17
|
+
# rubocop:disable Style/ParallelAssignment
|
18
|
+
@pageviews, @downloads = Hyrax::Analytics.daily_events('work-view'), Hyrax::Analytics.daily_events('file-set-download') if current_user.ability.admin?
|
19
|
+
# rubocop:enable Style/ParallelAssignment
|
20
20
|
respond_to do |format|
|
21
21
|
format.html
|
22
22
|
format.csv { export_data }
|
@@ -34,7 +34,7 @@ module Hyrax
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
|
37
|
+
private
|
38
38
|
|
39
39
|
def accessible_works
|
40
40
|
models = Hyrax::ModelRegistry.work_rdf_representations.map { |m| "\"#{m}\"" }
|
@@ -167,7 +167,7 @@ module Hyrax
|
|
167
167
|
return unless @file_set.class == ::FileSet
|
168
168
|
# We can tell if a Hyrax::FileSet was improperly cast because this AF method will
|
169
169
|
# return nil since its parent is not a ActiveFedora work.
|
170
|
-
@file_set = @file_set.valkyrie_resource if @file_set.parent&.id.nil?
|
170
|
+
@file_set = @file_set.valkyrie_resource if @file_set.respond_to?(:parent) && @file_set.parent&.id.nil?
|
171
171
|
end
|
172
172
|
|
173
173
|
def parent(file_set: curation_concern)
|
@@ -68,10 +68,10 @@ module Hyrax
|
|
68
68
|
mailbox = UserMailbox.new(user)
|
69
69
|
unread_notifications = mailbox.unread_count
|
70
70
|
link_to(hyrax.notifications_path,
|
71
|
-
'aria-
|
71
|
+
'aria-description' => mailbox.label(params[:locale]),
|
72
72
|
class: 'notify-number nav-link') do
|
73
73
|
capture do
|
74
|
-
concat tag.span('', class: 'fa fa-bell')
|
74
|
+
concat tag.span('', class: 'fa fa-bell', 'aria-label': t('hyrax.admin.sidebar.notifications'))
|
75
75
|
concat "\n"
|
76
76
|
concat tag.span(unread_notifications,
|
77
77
|
class: count_classes_for(unread_notifications))
|
@@ -15,7 +15,7 @@ module Hyrax
|
|
15
15
|
args[:data]['remove-text'] = args[:remove_text]
|
16
16
|
|
17
17
|
args[:data][:url] = hyrax.trophy_work_path(id)
|
18
|
-
link_to '#', id: 'action-highlight-work', class: args[:class], data: args[:data] do
|
18
|
+
link_to '#', id: 'action-highlight-work', role: args[:role], class: args[:class], data: args[:data] do
|
19
19
|
yield(text)
|
20
20
|
end
|
21
21
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module Hyrax
|
3
|
+
# Grants the user's edit access on the provided FileSet
|
4
|
+
module QueuedJobBehavior
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
queue_as Hyrax.config.ingest_queue_name
|
9
|
+
cattr_accessor :requeue_frequency
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def redis_queue
|
15
|
+
Valkyrie::IndexingAdapter.find(:redis_queue)
|
16
|
+
end
|
17
|
+
|
18
|
+
def requeue(**args)
|
19
|
+
self.class.set(wait_until: (self.class.requeue_frequency || 5.minutes).from_now).perform_later(**args)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -26,7 +26,7 @@ module Hyrax
|
|
26
26
|
def apply_depositor_metadata(resource, depositor)
|
27
27
|
depositor_id = depositor.respond_to?(:user_key) ? depositor.user_key : depositor
|
28
28
|
resource.depositor = depositor_id if resource.respond_to? :depositor=
|
29
|
-
|
29
|
+
resource.permission_manager.acl.grant(:edit).to(::User.find_by_user_key(depositor_id)).save
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
@@ -2,6 +2,11 @@
|
|
2
2
|
# Responsible for conditionally enqueuing the file and thumbnail migration
|
3
3
|
# logic of an ActiveFedora object.
|
4
4
|
class MigrateFilesToValkyrieJob < Hyrax::ApplicationJob
|
5
|
+
# Define a logger for this job
|
6
|
+
def logger
|
7
|
+
FileUtils.mkdir_p(Hyrax.config.working_path)
|
8
|
+
@logger ||= Logger.new(Hyrax.config.working_path.join('migrate_files_to_valkyrie_job.log'))
|
9
|
+
end
|
5
10
|
##
|
6
11
|
#
|
7
12
|
# @param resource [Hyrax::FileSet]
|
@@ -33,6 +38,7 @@ class MigrateFilesToValkyrieJob < Hyrax::ApplicationJob
|
|
33
38
|
# @todo should we trigger a job if the member is a child work?
|
34
39
|
paths = Hyrax::DerivativePath.derivatives_for_reference(resource)
|
35
40
|
paths.each do |path|
|
41
|
+
next unless File.size?(path) # skip blank files
|
36
42
|
container = container_for(path)
|
37
43
|
mime_type = Marcel::MimeType.for(extension: File.extname(path))
|
38
44
|
directives = { url: path, container: container, mime_type: mime_type }
|
@@ -50,27 +56,33 @@ class MigrateFilesToValkyrieJob < Hyrax::ApplicationJob
|
|
50
56
|
|
51
57
|
files = Hyrax.custom_queries.find_many_file_metadata_by_ids(ids: resource.file_ids)
|
52
58
|
files.each do |file|
|
53
|
-
|
54
|
-
|
55
|
-
|
59
|
+
begin
|
60
|
+
# If it doesn't start with fedora, we've likely already migrated it.
|
61
|
+
next unless /^fedora:/.match?(file.file_identifier.to_s)
|
62
|
+
resource.file_ids.delete(file.id)
|
56
63
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
64
|
+
Tempfile.create do |tempfile|
|
65
|
+
tempfile.binmode
|
66
|
+
tempfile.write(URI.open(file.file_identifier.to_s.gsub("fedora:", "http:")).read)
|
67
|
+
tempfile.rewind
|
61
68
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
69
|
+
# valkyrie_file = Hyrax.storage_adapter.upload(resource: resource, file: tempfile, original_filename: file.original_filename)
|
70
|
+
valkyrie_file = Hyrax::ValkyrieUpload.file(
|
71
|
+
filename: resource.label,
|
72
|
+
file_set: resource,
|
73
|
+
io: tempfile,
|
74
|
+
use: file.pcdm_use.select {|use| Hyrax::FileMetadata::Use.use_list.include?(use)},
|
75
|
+
user: User.find_or_initialize_by(User.user_key_field => resource.depositor),
|
76
|
+
mime_type: file.mime_type,
|
77
|
+
skip_derivatives: true
|
78
|
+
)
|
79
|
+
valkyrie_file = copy_attributes(valkyrie_file:, original_file: file)
|
80
|
+
Hyrax.persister.save(resource: valkyrie_file)
|
81
|
+
end
|
82
|
+
rescue StandardError => e
|
83
|
+
# Log errors specific to file migration
|
84
|
+
logger.error("Error migrating file #{file.id} for resource #{resource.id}: #{e.message}")
|
85
|
+
logger.error(e.backtrace.join("\n"))
|
74
86
|
end
|
75
87
|
end
|
76
88
|
# reindex the file set after migrating files to include characterization info
|
@@ -93,9 +105,9 @@ class MigrateFilesToValkyrieJob < Hyrax::ApplicationJob
|
|
93
105
|
#
|
94
106
|
# @param filename [String] the name of the derivative file: i.e. 'x-thumbnail.jpg'
|
95
107
|
# @return [String]
|
96
|
-
def container_for(
|
108
|
+
def container_for(path)
|
97
109
|
# we want the portion between the '-' and the '.'
|
98
|
-
file_blob = File.basename(
|
110
|
+
file_blob = File.basename(path, '.*').split('-').last
|
99
111
|
|
100
112
|
case file_blob
|
101
113
|
when 'thumbnail'
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# migrates a resource's sipity entity so it can be found
|
4
|
+
class MigrateSipityEntityJob < ApplicationJob
|
5
|
+
# input [String] id of a migrated resource
|
6
|
+
def perform(id:)
|
7
|
+
resource = Hyrax.query_service.find_by(id: id)
|
8
|
+
new_gid = Hyrax::GlobalID(resource).to_s
|
9
|
+
return if Sipity::Entity.find_by(proxy_for_global_id: new_gid)
|
10
|
+
|
11
|
+
work = resource.internal_resource.constantize.find(id)
|
12
|
+
original_gid = Hyrax::GlobalID(work).to_s
|
13
|
+
return if new_gid == original_gid
|
14
|
+
original_entity = Sipity::Entity.find_by(proxy_for_global_id: original_gid)
|
15
|
+
return if original_entity.nil?
|
16
|
+
original_entity.update(proxy_for_global_id: new_gid)
|
17
|
+
rescue ActiveFedora::ObjectNotFoundError
|
18
|
+
# this happens when the resource was never in Fedora so there is nothing to migrate.
|
19
|
+
# We don't want to retry the job so we don't raise an error.
|
20
|
+
end
|
21
|
+
end
|
@@ -404,8 +404,10 @@ module Hyrax
|
|
404
404
|
.select(:source_id)
|
405
405
|
.distinct
|
406
406
|
.pluck(:source_id)
|
407
|
-
|
408
|
-
Hyrax.
|
407
|
+
return false if ids.empty?
|
408
|
+
Hyrax::SolrQueryService.new.with_ids(ids: ids).query_result(rows: 1000)['response']['docs'].any? do |doc|
|
409
|
+
(Hyrax::ModelRegistry.admin_set_rdf_representations & doc['has_model_ssim']).present?
|
410
|
+
end
|
409
411
|
end
|
410
412
|
|
411
413
|
def registered_user?
|
@@ -82,9 +82,12 @@ module Hyrax
|
|
82
82
|
|
83
83
|
# Method to return the model
|
84
84
|
def hydra_model(classifier: nil)
|
85
|
+
# finds the model from the solr document
|
85
86
|
model = first('has_model_ssim')&.safe_constantize
|
86
|
-
|
87
|
-
|
87
|
+
# this returns nil if it isn't a valid model
|
88
|
+
resource_model = (first('has_model_ssim')&.+ 'Resource')&.safe_constantize if Hyrax.config.valkyrie_transition?
|
89
|
+
# if valkyrie_transition is enabled, we generally want to use the resource model if it exists
|
90
|
+
resource_model || model || model_classifier(classifier).classifier(self).best_model
|
88
91
|
end
|
89
92
|
|
90
93
|
def depositor(default = '')
|
@@ -44,16 +44,31 @@ module Hyrax
|
|
44
44
|
|
45
45
|
# @return [Array<RDF::URI>] list of all uses
|
46
46
|
def use_list
|
47
|
-
[
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
47
|
+
[
|
48
|
+
EXTRACTED_TEXT,
|
49
|
+
INTERMEDIATE_FILE,
|
50
|
+
ORIGINAL_FILE,
|
51
|
+
PRESERVATION_FILE,
|
52
|
+
SERVICE_FILE,
|
53
|
+
THUMBNAIL_IMAGE,
|
54
|
+
TRANSCRIPT
|
55
|
+
]
|
54
56
|
end
|
55
57
|
module_function :use_list
|
56
58
|
|
59
|
+
def keys
|
60
|
+
[
|
61
|
+
:extracted_file,
|
62
|
+
:intermediate_file,
|
63
|
+
:original_file,
|
64
|
+
:preservation_file,
|
65
|
+
:service_file,
|
66
|
+
:thumbnail_file,
|
67
|
+
:transcript_file
|
68
|
+
]
|
69
|
+
end
|
70
|
+
module_function :keys
|
71
|
+
|
57
72
|
##
|
58
73
|
# @param use [RDF::URI, Symbol]
|
59
74
|
#
|
@@ -76,7 +76,11 @@ module Hyrax
|
|
76
76
|
end
|
77
77
|
|
78
78
|
def account_info
|
79
|
-
@account_info ||=
|
79
|
+
@account_info ||= if account_json_string.is_a? Hash
|
80
|
+
account_json_string
|
81
|
+
else
|
82
|
+
JSON.parse(account_json_string)
|
83
|
+
end
|
80
84
|
end
|
81
85
|
|
82
86
|
KEYS.each do |key|
|
@@ -63,7 +63,7 @@ module Hyrax
|
|
63
63
|
def self.apply_depositor_metadata(resource, depositor)
|
64
64
|
depositor_id = depositor.respond_to?(:user_key) ? depositor.user_key : depositor
|
65
65
|
resource.depositor = depositor_id if resource.respond_to? :depositor=
|
66
|
-
|
66
|
+
resource.permission_manager.acl.grant(:edit).to(::User.find_by_user_key(depositor_id)).save
|
67
67
|
end
|
68
68
|
private_class_method :apply_depositor_metadata
|
69
69
|
end
|
@@ -107,13 +107,19 @@ class Hyrax::Characterization::ValkyrieCharacterizationService
|
|
107
107
|
end
|
108
108
|
|
109
109
|
# Assign values of the instance properties from the metadata mapping :prop => val
|
110
|
+
# @todo push exceptional per-property behavior into the mapping somehow?
|
110
111
|
# @return [Hash]
|
111
112
|
def apply_metadata(terms)
|
112
|
-
terms.
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
113
|
+
values_by_property(terms).each do |property, values|
|
114
|
+
value = if property == :mime_type
|
115
|
+
values.last
|
116
|
+
elsif [:height, :width].include?(property)
|
117
|
+
# keep only the max height or width
|
118
|
+
values.map(&:to_i).max.to_s
|
119
|
+
else
|
120
|
+
values
|
121
|
+
end
|
122
|
+
metadata.public_send("#{property}=", value)
|
117
123
|
end
|
118
124
|
end
|
119
125
|
|
@@ -127,13 +133,15 @@ class Hyrax::Characterization::ValkyrieCharacterizationService
|
|
127
133
|
end
|
128
134
|
end
|
129
135
|
|
130
|
-
|
131
|
-
#
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
136
|
+
# Map each term to the corresponding property
|
137
|
+
# (multiple terms can map to the same property),
|
138
|
+
# and gather all values for each property
|
139
|
+
# @return [Hash]
|
140
|
+
def values_by_property(terms)
|
141
|
+
terms.each_with_object({}) do |(term, value), property_values|
|
142
|
+
next unless (property = property_for(term))
|
143
|
+
|
144
|
+
(property_values[property] ||= []).concat(Array(value))
|
145
|
+
end
|
138
146
|
end
|
139
147
|
end
|
@@ -8,8 +8,9 @@ module Hyrax
|
|
8
8
|
[:find_ids_by_model]
|
9
9
|
end
|
10
10
|
|
11
|
-
def initialize(query_service:)
|
11
|
+
def initialize(query_service:, query_rows: 1_000)
|
12
12
|
@query_service = query_service
|
13
|
+
@query_rows = query_rows
|
13
14
|
end
|
14
15
|
|
15
16
|
attr_reader :query_service
|
@@ -23,14 +24,38 @@ module Hyrax
|
|
23
24
|
#
|
24
25
|
# @param model [Class]
|
25
26
|
# @param ids [Enumerable<#to_s>, Symbol]
|
27
|
+
# @param use_solr [Boolean]
|
26
28
|
#
|
27
29
|
# @return [Enumerable<Valkyrie::ID>]
|
28
|
-
def find_ids_by_model(model:, ids: :all)
|
29
|
-
|
30
|
+
def find_ids_by_model(model:, ids: :all, use_solr: true)
|
31
|
+
if use_solr
|
32
|
+
query_solr(model, ids)
|
33
|
+
else
|
34
|
+
return query_service.find_all_of_model(model: model).map(&:id) if ids == :all
|
35
|
+
query_service.find_many_by_ids(ids: ids).select do |resource|
|
36
|
+
resource.is_a?(model)
|
37
|
+
end.map(&:id)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def query_solr(model, ids)
|
44
|
+
return enum_for(:query_solr, model, ids) unless block_given?
|
45
|
+
model_name = Hyrax::ModelRegistry.rdf_representations_from(Array(model)).first
|
46
|
+
|
47
|
+
solr_query = "_query_:\"{!raw f=has_model_ssim}#{model_name}\""
|
48
|
+
solr_response = Hyrax::SolrService.get(solr_query, fl: 'id', rows: @query_rows)['response']
|
49
|
+
|
50
|
+
loop do
|
51
|
+
response_docs = solr_response['docs']
|
52
|
+
response_docs.select! { |doc| ids.include?(doc['id']) } unless ids == :all
|
53
|
+
|
54
|
+
response_docs.each { |doc| yield doc['id'] }
|
30
55
|
|
31
|
-
|
32
|
-
|
33
|
-
end
|
56
|
+
break if (solr_response['start'] + solr_response['docs'].count) >= solr_response['numFound']
|
57
|
+
solr_response = Hyrax::SolrService.get(solr_query, fl: 'id', rows: @query_rows, start: solr_response['start'] + @query_rows)['response']
|
58
|
+
end
|
34
59
|
end
|
35
60
|
end
|
36
61
|
end
|
@@ -33,23 +33,24 @@ module Hyrax
|
|
33
33
|
# * use work the file_set is in
|
34
34
|
# No other object types are supported by this view.
|
35
35
|
def self.build_service_object_from(form:, ability:)
|
36
|
-
|
36
|
+
obj = form.object
|
37
|
+
if obj.respond_to?(:model) && obj.model.work?
|
37
38
|
# The provided form object is a work form.
|
38
|
-
new(object:
|
39
|
-
elsif
|
39
|
+
new(object: obj, ability: ability)
|
40
|
+
elsif obj.respond_to?(:model) && obj.model.file_set?
|
40
41
|
# The provided form object is a FileSet form. For Valkyrie forms
|
41
42
|
# (+Hyrax::Forms::FileSetForm+), +:in_works_ids+ is prepopulated onto
|
42
43
|
# the form object itself. For +Hyrax::Forms::FileSetEditForm+, the
|
43
44
|
# +:in_works+ method is present on the wrapped +:model+.
|
44
|
-
if
|
45
|
-
object_id =
|
45
|
+
if obj.is_a?(Hyrax.config.file_set_form)
|
46
|
+
object_id = obj.in_works_ids.first
|
46
47
|
new(object: Hyrax.query_service.find_by(id: object_id), ability: ability)
|
47
48
|
else
|
48
|
-
new(object:
|
49
|
+
new(object: obj.model.in_works.first, ability: ability)
|
49
50
|
end
|
50
|
-
elsif
|
51
|
+
elsif obj.file_set?
|
51
52
|
# The provided form object is a FileSet.
|
52
|
-
new(object:
|
53
|
+
new(object: obj.in_works.first, ability: ability)
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
@@ -50,9 +50,9 @@ module Hyrax
|
|
50
50
|
private
|
51
51
|
|
52
52
|
def create_workflow_entity!
|
53
|
-
Sipity::Entity.
|
54
|
-
|
55
|
-
|
53
|
+
Sipity::Entity.find_or_create_by!(proxy_for_global_id: Hyrax::GlobalID(work).to_s,
|
54
|
+
workflow: workflow_for(work),
|
55
|
+
workflow_state: nil)
|
56
56
|
end
|
57
57
|
|
58
58
|
def assign_specific_roles_to(entity:)
|
@@ -14,7 +14,8 @@
|
|
14
14
|
<%= link_to "My Profile", hyrax.dashboard_profile_path(current_user), class: 'dropdown-item' %>
|
15
15
|
<%= link_to t("hyrax.toolbar.dashboard.menu"), hyrax.dashboard_path, class: "dropdown-item" %>
|
16
16
|
<div class="dropdown-divider"></div>
|
17
|
-
<%=
|
17
|
+
<%= button_to t("hyrax.toolbar.profile.logout"), main_app.destroy_user_session_path, class: "dropdown-item",
|
18
|
+
method: ::Devise.sign_out_via %>
|
18
19
|
</div>
|
19
20
|
</li>
|
20
21
|
<% else %>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<div class="card">
|
2
|
-
|
2
|
+
|
3
3
|
<div class="card-header">
|
4
4
|
<h4><%= t('.top_collections') %>
|
5
5
|
<div class="btn-group float-right">
|
@@ -41,15 +41,11 @@
|
|
41
41
|
</tbody>
|
42
42
|
</table>
|
43
43
|
</div>
|
44
|
-
|
44
|
+
|
45
45
|
<div class="card-footer">
|
46
46
|
<div class="float-right">
|
47
|
-
<%= paginate @top_collections %>
|
47
|
+
<%= paginate @top_collections, outer_window: 2, theme: 'blacklight' %>
|
48
48
|
</div>
|
49
49
|
</div>
|
50
50
|
|
51
51
|
</div>
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|