hyrax 2.7.0 → 2.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +60 -33
  3. data/.gitignore +1 -0
  4. data/.regen +1 -0
  5. data/README.md +4 -4
  6. data/app/actors/hyrax/actors/attach_members_actor.rb +9 -2
  7. data/app/actors/hyrax/actors/collections_membership_actor.rb +10 -11
  8. data/app/assets/javascripts/hyrax.js +1 -0
  9. data/app/assets/javascripts/hyrax/autocomplete.es6 +29 -0
  10. data/app/assets/javascripts/hyrax/editor.es6 +9 -10
  11. data/app/assets/javascripts/hyrax/skip_to_content.js +15 -0
  12. data/app/controllers/concerns/hyrax/local_file_downloads_controller_behavior.rb +2 -1
  13. data/app/controllers/concerns/hyrax/works_controller_behavior.rb +18 -7
  14. data/app/controllers/hyrax/users_controller.rb +1 -1
  15. data/app/helpers/hyrax/hyrax_helper_behavior.rb +1 -0
  16. data/app/helpers/hyrax/work_form_helper.rb +48 -0
  17. data/app/indexers/hyrax/deep_indexing_service.rb +21 -12
  18. data/app/indexers/hyrax/file_set_indexer.rb +6 -1
  19. data/app/jobs/embargo_expiry_job.rb +15 -0
  20. data/app/jobs/iiif_manifest_cache_prewarm_job.rb +16 -0
  21. data/app/jobs/lease_expiry_job.rb +15 -0
  22. data/app/models/concerns/hyrax/solr_document/characterization.rb +5 -1
  23. data/app/models/concerns/hyrax/solr_document/metadata.rb +9 -7
  24. data/app/models/concerns/hyrax/solr_document/ordered_members.rb +46 -0
  25. data/app/models/concerns/hyrax/solr_document_behavior.rb +10 -0
  26. data/app/models/hyrax/uploaded_file.rb +0 -2
  27. data/app/presenters/hyrax/displays_image.rb +41 -15
  28. data/app/presenters/hyrax/file_set_presenter.rb +5 -0
  29. data/app/presenters/hyrax/iiif_manifest_presenter.rb +232 -0
  30. data/app/presenters/hyrax/member_presenter_factory.rb +1 -7
  31. data/app/search_builders/hyrax/embargo_search_builder.rb +1 -1
  32. data/app/search_builders/hyrax/lease_search_builder.rb +1 -1
  33. data/app/services/hyrax/caching_iiif_manifest_builder.rb +53 -0
  34. data/app/services/hyrax/file_set_csv_service.rb +1 -0
  35. data/app/services/hyrax/identifier/builder.rb +45 -0
  36. data/app/services/hyrax/identifier/dispatcher.rb +61 -0
  37. data/app/services/hyrax/identifier/registrar.rb +41 -0
  38. data/app/services/hyrax/manifest_builder_service.rb +88 -0
  39. data/app/services/hyrax/versioning_service.rb +9 -0
  40. data/app/services/hyrax/workflow/workflow_schema.rb +92 -32
  41. data/app/views/hyrax/base/_form.html.erb +1 -1
  42. data/app/views/hyrax/base/_form_progress.html.erb +4 -0
  43. data/app/views/hyrax/base/_guts4form.html.erb +7 -1
  44. data/app/views/hyrax/batch_uploads/_form.html.erb +1 -1
  45. data/app/views/hyrax/dashboard/_sidebar.html.erb +1 -1
  46. data/config/features.rb +4 -0
  47. data/hyrax.gemspec +9 -6
  48. data/lib/generators/hyrax/templates/config/initializers/hyrax.rb +5 -0
  49. data/lib/generators/hyrax/templates/config/locales/hyrax.es.yml +1 -1
  50. data/lib/hyrax.rb +2 -0
  51. data/lib/hyrax/configuration.rb +23 -4
  52. data/lib/hyrax/engine.rb +1 -0
  53. data/lib/hyrax/specs/shared_specs.rb +1 -0
  54. data/lib/hyrax/specs/shared_specs/identifiers.rb +27 -0
  55. data/lib/hyrax/version.rb +1 -1
  56. data/template.rb +1 -1
  57. metadata +108 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0b78347854928dad8c8ee7c063242ffcef844aee8427243009be48ca4ec809c2
4
- data.tar.gz: cc0bf69bb012226fc582822e86d395cce0de87da0d749ee45104cc5c78cfaacd
3
+ metadata.gz: fdad61bdb40ae80fa4693bf81f3fc42a581943bdb77bee4fbaaa10367ae0bb9c
4
+ data.tar.gz: e83ba7521508d26a4e520fc6ab002be912594c78f1fabc066c8d5b887733ba3c
5
5
  SHA512:
6
- metadata.gz: d6ff706b2405317225f143f78f5b1903dbf676d7d0d7846cf1b3d144f530e568792c92184f818b07cabdcd8479b2a5eaf27bbe17a66c08a4b76c67559321fe2b
7
- data.tar.gz: 07cff94f6fd86bc3a796d0a1d1af3879b5acebc4d36017f04b63d593b56c53f2d223851f672f232fbb344042fdd64d75393f281036e19de95527ba5fcb6bab65
6
+ metadata.gz: b8bf649b4432aeaa409734defa1773e5be9ef8ffe5993a02ede4a41aed7c541ff4c0b6eb312ade95bfd6710317b98ff6bf076f79e637ed5e4c25df6773680dac
7
+ data.tar.gz: 9deb1668640448edc64ff4576205dc9d5268692d43f730b361756b8f62bb794439b20ce88dc5a740afdd25349ea08b3884b27408d0f2726875861934402f51c7
@@ -6,16 +6,13 @@ jobs:
6
6
  parameters:
7
7
  ruby_version:
8
8
  type: string
9
- default: 2.5.5
9
+ default: 2.5.8
10
10
  bundler_version:
11
11
  type: string
12
12
  default: 1.17.3
13
13
  rails_version:
14
14
  type: string
15
- default: '5.2.2'
16
- cache_version:
17
- type: string
18
- default: '1-2.x'
15
+ default: '5.2.4.3'
19
16
  executor:
20
17
  name: 'samvera/ruby'
21
18
  ruby_version: << parameters.ruby_version >>
@@ -28,6 +25,7 @@ jobs:
28
25
  - samvera/bundle_for_gem:
29
26
  ruby_version: << parameters.ruby_version >>
30
27
  bundler_version: << parameters.bundler_version >>
28
+ cache_version: '{{ checksum ".regen" }}'
31
29
  project: hyrax
32
30
  - persist_to_workspace:
33
31
  root: ~/
@@ -40,9 +38,6 @@ jobs:
40
38
  ruby_version:
41
39
  type: string
42
40
  default: 2.5.5
43
- cache_version:
44
- type: string
45
- default: '1-2.x'
46
41
  executor:
47
42
  name: 'samvera/ruby'
48
43
  ruby_version: << parameters.ruby_version >>
@@ -56,16 +51,13 @@ jobs:
56
51
  parameters:
57
52
  ruby_version:
58
53
  type: string
59
- default: 2.5.5
54
+ default: 2.5.8
60
55
  bundler_version:
61
56
  type: string
62
57
  default: 1.17.3
63
58
  rails_version:
64
59
  type: string
65
- default: '5.2.2'
66
- cache_version:
67
- type: string
68
- default: '1-2.x'
60
+ default: '5.2.4.3'
69
61
  executor:
70
62
  name: 'samvera/ruby'
71
63
  ruby_version: << parameters.ruby_version >>
@@ -78,11 +70,11 @@ jobs:
78
70
  - attach_workspace:
79
71
  at: ~/
80
72
  - samvera/engine_cart_generate:
81
- cache_key: v<< parameters.cache_version >>--internal-test-app-{{ checksum "hyrax.gemspec" }}-{{ checksum "spec/test_app_templates/lib/generators/test_app_generator.rb" }}-{{ checksum "lib/generators/hyrax/install_generator.rb" }}-<< parameters.rails_version >>-<< parameters.ruby_version >>
73
+ cache_key: v1-2.x-internal-test-app-{{ checksum "hyrax.gemspec" }}-{{ checksum ".regen" }}-<< parameters.rails_version >>-<< parameters.ruby_version >>
82
74
  - samvera/bundle_for_gem:
83
75
  ruby_version: << parameters.ruby_version >>
84
76
  bundler_version: << parameters.bundler_version >>
85
- cache_version: << parameters.cache_version >>
77
+ cache_version: '{{ checksum ".regen" }}'
86
78
  project: hyrax
87
79
  - persist_to_workspace:
88
80
  root: ~/
@@ -94,13 +86,10 @@ jobs:
94
86
  parameters:
95
87
  ruby_version:
96
88
  type: string
97
- default: 2.5.5
89
+ default: 2.5.8
98
90
  bundler_version:
99
91
  type: string
100
92
  default: 1.17.3
101
- cache_version:
102
- type: string
103
- default: '1-2.x'
104
93
  executor:
105
94
  name: 'samvera/ruby_fcrepo_solr_redis'
106
95
  ruby_version: << parameters.ruby_version >>
@@ -117,39 +106,77 @@ jobs:
117
106
  - samvera/bundle_for_gem:
118
107
  ruby_version: << parameters.ruby_version >>
119
108
  bundler_version: << parameters.bundler_version >>
120
- cache_version: << parameters.cache_version >>
109
+ cache_version: '{{ checksum ".regen" }}'
121
110
  project: hyrax
122
111
  - samvera/parallel_rspec
123
112
 
124
113
  workflows:
125
114
  version: 2
126
- ci:
115
+ ruby2-5rails5-1:
127
116
  jobs:
128
117
  - bundle:
129
- ruby_version: "2.5.5"
118
+ ruby_version: "2.5.8"
130
119
  rails_version: "5.1.7"
131
- cache_version: "1-2.x"
132
120
  - lint:
133
- ruby_version: "2.5.5"
134
- cache_version: "1-2.x"
121
+ ruby_version: "2.5.8"
135
122
  requires:
136
123
  - bundle
137
124
  - build:
138
- ruby_version: "2.5.5"
125
+ ruby_version: "2.5.8"
139
126
  rails_version: "5.1.7"
140
- cache_version: "1-2.x"
141
127
  requires:
142
128
  - bundle
143
129
  - test:
144
- name: "ruby2-5-5"
145
- ruby_version: "2.5.5"
130
+ name: "rails5-1"
131
+ ruby_version: "2.5.8"
146
132
  requires:
147
133
  - build
148
134
  - lint
135
+ ruby2-5rails5-2:
136
+ jobs:
137
+ - bundle:
138
+ ruby_version: "2.5.8"
139
+ rails_version: "5.2.4.3"
140
+ - build:
141
+ ruby_version: "2.5.8"
142
+ rails_version: "5.2.4.3"
143
+ requires:
144
+ - bundle
149
145
  - test:
150
- name: "ruby2-6-2"
151
- ruby_version: "2.6.2"
152
- cache_version: "1-2.x"
146
+ name: "ruby2-5-8"
147
+ ruby_version: "2.5.8"
148
+ requires:
149
+ - build
150
+ ruby2-6rails5-2:
151
+ jobs:
152
+ - bundle:
153
+ ruby_version: "2.6.6"
154
+ rails_version: "5.2.4.3"
155
+ - build:
156
+ ruby_version: "2.6.6"
157
+ rails_version: "5.2.4.3"
158
+ requires:
159
+ - bundle
160
+ - test:
161
+ name: "ruby2-6-6"
162
+ ruby_version: "2.6.6"
163
+ requires:
164
+ - build
165
+ ruby2-7rails5-2:
166
+ jobs:
167
+ - bundle:
168
+ ruby_version: "2.7.1"
169
+ rails_version: "5.2.4.3"
170
+ bundler_version: "2.1.2"
171
+ - build:
172
+ ruby_version: "2.7.1"
173
+ rails_version: "5.2.4.3"
174
+ bundler_version: "2.1.2"
175
+ requires:
176
+ - bundle
177
+ - test:
178
+ name: "ruby2-7-1"
179
+ ruby_version: "2.7.1"
180
+ bundler_version: "2.1.2"
153
181
  requires:
154
182
  - build
155
- - lint
data/.gitignore CHANGED
@@ -78,3 +78,4 @@ _yardoc
78
78
  lib/bundler/man
79
79
  spec/reports
80
80
  /spec/examples.txt
81
+ node_modules
data/.regen ADDED
@@ -0,0 +1 @@
1
+ 3
data/README.md CHANGED
@@ -128,7 +128,7 @@ Note here that the following commands assume you're setting up Hyrax in a develo
128
128
 
129
129
  First, you'll need a working Ruby installation. You can install this via your operating system's package manager -- you are likely to get farther with OSX, Linux, or UNIX than Windows but your mileage may vary -- but we recommend using a Ruby version manager such as [RVM](https://rvm.io/) or [rbenv](https://github.com/sstephenson/rbenv).
130
130
 
131
- Hyrax supports Ruby 2.3, 2.4 and 2.5. When starting a new project, we recommend using the latest Ruby 2.5 version.
131
+ Hyrax supports Ruby 2.3 and up. When starting a new project, we recommend using the latest Ruby 2.7 version.
132
132
 
133
133
  ## Redis
134
134
 
@@ -138,11 +138,11 @@ Starting up Redis will depend on your operating system, and may in fact already
138
138
 
139
139
  ## Rails
140
140
 
141
- Hyrax requires Rails 5. We recommend the latest Rails 5.1 release.
141
+ Hyrax 2.x supports Rails 5.1 and 5.2. We recommend the latest Rails 5.2 release.
142
142
 
143
143
  ```
144
144
  # If you don't already have Rails at your disposal...
145
- gem install rails -v 5.1.6
145
+ gem install rails -v '5.2.4.3'
146
146
  ```
147
147
 
148
148
  ### JavaScript runtime
@@ -158,7 +158,7 @@ NOTE: The steps need to be done in order to create a new Hyrax based app.
158
158
  Generate a new Rails application using the template.
159
159
 
160
160
  ```
161
- rails _5.1.6_ new my_app -m https://raw.githubusercontent.com/samvera/hyrax/v2.6.0/template.rb
161
+ rails _5.2.4.3_ new my_app -m https://raw.githubusercontent.com/samvera/hyrax/v2.9.0/template.rb
162
162
  ```
163
163
 
164
164
  Generating a new Rails application using Hyrax's template above takes cares of a number of steps for you, including:
@@ -30,11 +30,18 @@ module Hyrax
30
30
  # checking for existing works to avoid rewriting/loading works that are
31
31
  # already attached
32
32
  existing_works = env.curation_concern.member_ids
33
+ boolean_type_caster = ActiveModel::Type::Boolean.new
34
+
33
35
  attributes_collection.each do |attributes|
34
36
  next if attributes['id'].blank?
35
- if existing_works.include?(attributes['id'])
36
- remove(env.curation_concern, attributes['id']) if has_destroy_flag?(attributes)
37
+ if boolean_type_caster.cast(attributes['_destroy'])
38
+ # Likely someone in the UI sought to add the collection, then
39
+ # changed their mind and checked the "delete" checkbox and posted
40
+ # their update.
41
+ next unless existing_works.include?(attributes['id'])
42
+ remove(env.curation_concern, attributes['id'])
37
43
  else
44
+ next if existing_works.include?(attributes['id'])
38
45
  add(env, attributes['id'])
39
46
  end
40
47
  end
@@ -31,7 +31,7 @@ module Hyrax
31
31
  # @param env [Hyrax::Actors::Enviornment]
32
32
  # @return [Boolean]
33
33
  #
34
- # rubocop:disable Metrics/MethodLength
34
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
35
35
  # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
36
36
  def assign_nested_attributes_for_collection(env)
37
37
  attributes_collection = env.attributes.delete(:member_of_collections_attributes)
@@ -46,18 +46,24 @@ module Hyrax
46
46
  attributes_collection = attributes_collection.sort_by { |i, _| i.to_i }.map { |_, attributes| attributes }
47
47
  # checking for existing works to avoid rewriting/loading works that are already attached
48
48
  existing_collections = env.curation_concern.member_of_collection_ids
49
+ boolean_type_caster = ActiveModel::Type::Boolean.new
49
50
  attributes_collection.each do |attributes|
50
51
  next if attributes['id'].blank?
51
- if existing_collections.include?(attributes['id'])
52
- remove(env.curation_concern, attributes['id']) if has_destroy_flag?(attributes)
52
+ if boolean_type_caster.cast(attributes['_destroy'])
53
+ # Likely someone in the UI sought to add the collection, then
54
+ # changed their mind and checked the "delete" checkbox and posted
55
+ # their update.
56
+ next unless existing_collections.include?(attributes['id'])
57
+ remove(env.curation_concern, attributes['id'])
53
58
  else
59
+ next if existing_collections.include?(attributes['id'])
54
60
  add(env, attributes['id'])
55
61
  end
56
62
  end
57
63
 
58
64
  true
59
65
  end
60
- # rubocop:enable Metrics/MethodLength
66
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
61
67
  # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
62
68
 
63
69
  ##
@@ -115,13 +121,6 @@ module Hyrax
115
121
  curation_concern.member_of_collections.delete(collection)
116
122
  end
117
123
 
118
- # Determines if a hash contains a truthy _destroy key.
119
- # rubocop:disable Naming/PredicateName
120
- def has_destroy_flag?(hash)
121
- ActiveFedora::Type::Boolean.new.cast(hash['_destroy'])
122
- end
123
- # rubocop:enable Naming/PredicateName
124
-
125
124
  # Extact a singleton collection id from the collection attributes and save it in env. Later in the actor stack,
126
125
  # in apply_permission_template_actor.rb, `env.attributes[:collection_id]` will be used to apply the
127
126
  # permissions of the collection to the created work. With one and only one collection, the work is seen as
@@ -104,6 +104,7 @@
104
104
  //= require hyrax/tabbed_form
105
105
  //= require hyrax/turbolinks_events
106
106
  //= require hyrax/i18n_helper
107
+ //= require hyrax/skip_to_content
107
108
 
108
109
  // this needs to be after batch_select so that the form ids get setup correctly
109
110
  //= require hyrax/batch_edit
@@ -10,6 +10,34 @@ export default class Autocomplete {
10
10
  * @param {string} url - The url for the autocompete search endpoint
11
11
  */
12
12
  setup (element, fieldName, url) {
13
+ if(element.data('autocomplete-type') && element.data('autocomplete-type').length > 0) {
14
+ this.byDataAttribute(element, url)
15
+ } else {
16
+ this.byFieldName(element, fieldName, url)
17
+ }
18
+ }
19
+
20
+ byDataAttribute(element, url) {
21
+ let type = element.data('autocomplete-type')
22
+ let exlude = element.data('exclude-work')
23
+ if(type === 'resource' && exclude.length > 0) {
24
+ new Resource(
25
+ element,
26
+ url,
27
+ { excluding: exclude }
28
+ )
29
+ } else if(type === 'resource' ) {
30
+ new Resource(
31
+ element,
32
+ url)
33
+ } else if(type === 'linked') {
34
+ new LinkedData(element, url)
35
+ } else {
36
+ new Default(element, url)
37
+ }
38
+ }
39
+
40
+ byFieldName(element, fieldName, url) {
13
41
  switch (fieldName) {
14
42
  case 'work':
15
43
  new Resource(
@@ -30,4 +58,5 @@ export default class Autocomplete {
30
58
  break
31
59
  }
32
60
  }
61
+
33
62
  }
@@ -53,17 +53,16 @@ export default class {
53
53
  $('[data-autocomplete]').each((function() {
54
54
  var elem = $(this)
55
55
  autocomplete.setup(elem, elem.data('autocomplete'), elem.data('autocompleteUrl'))
56
+ elem.parents('.multi_value.form-group').manage_fields({
57
+ add: function(e, element) {
58
+ var elem = $(element)
59
+ // Don't mark an added element as readonly even if previous element was
60
+ // Enable before initializing, as otherwise LinkedData fields remain disabled
61
+ elem.attr('readonly', false)
62
+ autocomplete.setup(elem, elem.data('autocomplete'), elem.data('autocompleteUrl'))
63
+ }
64
+ })
56
65
  }))
57
-
58
- $('.multi_value.form-group').manage_fields({
59
- add: function(e, element) {
60
- var elem = $(element)
61
- // Don't mark an added element as readonly even if previous element was
62
- // Enable before initializing, as otherwise LinkedData fields remain disabled
63
- elem.attr('readonly', false)
64
- autocomplete.setup(elem, elem.data('autocomplete'), elem.data('autocompleteUrl'))
65
- }
66
- })
67
66
  }
68
67
 
69
68
  // initialize any controlled vocabulary widgets
@@ -0,0 +1,15 @@
1
+ // This code is to implement skip_to_content
2
+
3
+ Blacklight.onLoad(function () {
4
+ $(".skip-to-content").click(function(event) {
5
+ event.preventDefault();
6
+ // element to focus on
7
+ let skipTo = '#' + $(this)[0].firstElementChild.hash.split('#')[1];
8
+
9
+ // Setting 'tabindex' to -1 takes an element out of normal
10
+ // tab flow but allows it to be focused via javascript
11
+ $(skipTo).attr('tabindex', -1).on('blur focusout', function () {
12
+ $(this).removeAttr('tabindex');
13
+ }).focus();
14
+ });
15
+ });
@@ -29,6 +29,7 @@ module Hyrax
29
29
  end
30
30
 
31
31
  def send_local_file_contents
32
+ return unless stale?(last_modified: local_file_last_modified, template: false)
32
33
  self.status = 200
33
34
  prepare_local_file_headers
34
35
  # For derivatives stored on the local file system
@@ -65,7 +66,7 @@ module Hyrax
65
66
  response.headers['Content-Type'] = local_file_mime_type
66
67
  response.headers['Content-Length'] ||= local_file_size.to_s
67
68
  # Prevent Rack::ETag from calculating a digest over body
68
- response.headers['Last-Modified'] = local_file_last_modified.utc.strftime("%a, %d %b %Y %T GMT")
69
+ response.headers['Last-Modified'] ||= local_file_last_modified.httpdate
69
70
  self.content_type = local_file_mime_type
70
71
  end
71
72
 
@@ -10,10 +10,11 @@ module Hyrax
10
10
  with_themed_layout :decide_layout
11
11
  copy_blacklight_config_from(::CatalogController)
12
12
 
13
- class_attribute :_curation_concern_type, :show_presenter, :work_form_service, :search_builder_class
13
+ class_attribute :_curation_concern_type, :show_presenter, :work_form_service, :search_builder_class, :iiif_manifest_builder
14
14
  self.show_presenter = Hyrax::WorkShowPresenter
15
15
  self.work_form_service = Hyrax::WorkFormService
16
16
  self.search_builder_class = WorkSearchBuilder
17
+ self.iiif_manifest_builder = (Flipflop.cache_work_iiif_manifest? ? Hyrax::CachingIiifManifestBuilder.new : Hyrax::ManifestBuilderService.new)
17
18
  attr_accessor :curation_concern
18
19
  helper_method :curation_concern, :contextual_path
19
20
 
@@ -127,14 +128,28 @@ module Hyrax
127
128
 
128
129
  def manifest
129
130
  headers['Access-Control-Allow-Origin'] = '*'
131
+
132
+ json = iiif_manifest_builder.manifest_for(presenter: iiif_manifest_presenter)
133
+
130
134
  respond_to do |wants|
131
- wants.json { render json: manifest_builder.to_h }
132
- wants.html { render json: manifest_builder.to_h }
135
+ wants.json { render json: json }
136
+ wants.html { render json: json }
133
137
  end
134
138
  end
135
139
 
136
140
  private
137
141
 
142
+ def iiif_manifest_builder
143
+ self.class.iiif_manifest_builder
144
+ end
145
+
146
+ def iiif_manifest_presenter
147
+ IiifManifestPresenter.new(curation_concern_from_search_results).tap do |p|
148
+ p.hostname = request.hostname
149
+ p.ability = current_ability
150
+ end
151
+ end
152
+
138
153
  def user_collections
139
154
  collections_service.search_results(:deposit)
140
155
  end
@@ -157,10 +172,6 @@ module Hyrax
157
172
  @form = work_form_service.build(curation_concern, current_ability, self)
158
173
  end
159
174
 
160
- def manifest_builder
161
- ::IIIFManifest::ManifestFactory.new(presenter)
162
- end
163
-
164
175
  def actor
165
176
  @actor ||= Hyrax::CurationConcern.actor
166
177
  end