hyrax 2.1.0.rc3 → 2.1.0.rc4
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/README.md +9 -2
- data/app/assets/javascripts/hyrax/save_work/visibility_component.es6 +4 -4
- data/app/controllers/concerns/hyrax/controller.rb +15 -0
- data/app/controllers/concerns/hyrax/works_controller_behavior.rb +3 -1
- data/app/helpers/hyrax/hyrax_helper_behavior.rb +8 -0
- data/app/jobs/attach_files_to_work_job.rb +1 -1
- data/app/presenters/hyrax/admin_set_presenter.rb +1 -1
- data/app/presenters/hyrax/collection_presenter.rb +1 -1
- data/app/presenters/hyrax/file_set_presenter.rb +10 -6
- data/app/presenters/hyrax/member_presenter_factory.rb +10 -10
- data/app/presenters/hyrax/work_show_presenter.rb +43 -4
- data/app/renderers/hyrax/renderers/faceted_attribute_renderer.rb +1 -1
- data/app/renderers/hyrax/renderers/linked_attribute_renderer.rb +1 -1
- data/app/search_builders/hyrax/catalog_search_builder.rb +14 -1
- data/app/services/hyrax/collections/permissions_service.rb +13 -0
- data/app/views/hyrax/base/_items.html.erb +9 -1
- data/app/views/hyrax/dashboard/collections/_form_for_select_collection.html.erb +4 -3
- data/lib/generators/hyrax/templates/catalog_controller.rb +1 -1
- data/lib/generators/hyrax/templates/config/initializers/hyrax.rb +4 -0
- data/lib/hyrax/configuration.rb +5 -0
- data/lib/hyrax/version.rb +1 -1
- data/spec/features/catalog_search_spec.rb +41 -0
- data/spec/helpers/hyrax_helper_spec.rb +30 -0
- data/spec/lib/hyrax/configuration_spec.rb +1 -0
- data/spec/presenters/hyrax/admin_set_presenter_spec.rb +1 -1
- data/spec/presenters/hyrax/collection_presenter_spec.rb +1 -1
- data/spec/presenters/hyrax/work_show_presenter_spec.rb +79 -4
- data/spec/renderers/hyrax/renderers/faceted_attribute_renderer_spec.rb +3 -3
- data/spec/renderers/hyrax/renderers/linked_attribute_renderer_spec.rb +2 -2
- data/spec/search_builders/hyrax/catalog_search_builder_spec.rb +35 -0
- data/spec/services/hyrax/collections/permissions_service_spec.rb +14 -0
- data/spec/views/hyrax/base/_items.html.erb_spec.rb +18 -24
- data/spec/views/hyrax/my/collections/_list_collections.html.erb_spec.rb +1 -1
- data/template.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf48eeb6b1a64bc4d19de32c47c6c776387ec40d
|
4
|
+
data.tar.gz: f5ee75a59cd3f27fa135d4a623e47430594037d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f7699b73766c7b747377e563f16049a02339cefb40cac5b2190795cb1045fce60a64f85d0c4571851fe36ca6ef7f53e16a566faca7711798627cbf15a9746f8e
|
7
|
+
data.tar.gz: b528b5192fc06718fecb1130b4d17b792a4e11b116a7a383091193632b62ccf0d29901004a599f2a4abbf7c9377ef98d8b6230bdc028569b8ccb73b2fe77ba48
|
data/README.md
CHANGED
@@ -63,7 +63,7 @@ The Samvera community is here to help. Please see our [support guide](./.github/
|
|
63
63
|
# Getting started
|
64
64
|
|
65
65
|
This document contains instructions specific to setting up an app with __Hyrax
|
66
|
-
v2.1.0.
|
66
|
+
v2.1.0.rc4__. If you are looking for instructions on installing a different
|
67
67
|
version, be sure to select the appropriate branch or tag from the drop-down
|
68
68
|
menu above.
|
69
69
|
|
@@ -162,7 +162,7 @@ NOTE: The steps need to be done in order to create a new Hyrax based app.
|
|
162
162
|
Generate a new Rails application using the template.
|
163
163
|
|
164
164
|
```
|
165
|
-
rails _5.1.6_ new my_app -m https://raw.githubusercontent.com/samvera/hyrax/v2.1.0.
|
165
|
+
rails _5.1.6_ new my_app -m https://raw.githubusercontent.com/samvera/hyrax/v2.1.0.rc4/template.rb
|
166
166
|
```
|
167
167
|
|
168
168
|
Generating a new Rails application using Hyrax's template above takes cares of a number of steps for you, including:
|
@@ -188,6 +188,13 @@ Notes:
|
|
188
188
|
* This web server is purely for development purposes. You will want to use a more fully featured [web server](#web-server) for production-like environments.
|
189
189
|
* You have the option to start each of these services individually. More information on [solr_wrapper](https://github.com/cbeer/solr_wrapper) and [fcrepo_wrapper](https://github.com/cbeer/fcrepo_wrapper) will help you set this up. Start rails with `rails s`.
|
190
190
|
|
191
|
+
### Avoid Performance Issues with solr-suggest
|
192
|
+
|
193
|
+
*Recommended for all Hyrax apps.*
|
194
|
+
|
195
|
+
It is strongly suggested that you turn off solr-suggest. Details on why and how to do this are in
|
196
|
+
[Fix performance issue caused by solr-suggest](https://github.com/samvera/hyrax/wiki/Troubleshooting-Migration-from-2.0.x-to-2.1.0#fix-performance-issue-caused-by-solr-suggest-after-200-objects-are-in-the-repository).
|
197
|
+
|
191
198
|
## Start background workers
|
192
199
|
|
193
200
|
Many of the services performed by Hyrax are resource intensive, and therefore are well suited to running as background jobs that can be managed and executed by a message queuing system. Examples include:
|
@@ -8,7 +8,7 @@ export default class VisibilityComponent {
|
|
8
8
|
this.element = element
|
9
9
|
this.adminSetWidget = adminSetWidget
|
10
10
|
this.form = element.closest('form')
|
11
|
-
|
11
|
+
this.element.find('.collapse').collapse({ toggle: false })
|
12
12
|
element.find("[type='radio']").on('change', () => { this.showForm() })
|
13
13
|
// Ensure any disabled options are re-enabled when form submits
|
14
14
|
this.form.on('submit', () => { this.enableAllOptions() })
|
@@ -22,7 +22,7 @@ export default class VisibilityComponent {
|
|
22
22
|
|
23
23
|
// Collapse all Visibility sub-options
|
24
24
|
collapseAll() {
|
25
|
-
|
25
|
+
this.element.find('.collapse').collapse('hide');
|
26
26
|
}
|
27
27
|
|
28
28
|
// Open the selected Visibility's sub-options, collapsing all others
|
@@ -33,8 +33,8 @@ export default class VisibilityComponent {
|
|
33
33
|
|
34
34
|
if(target) {
|
35
35
|
// Show the target suboption and hide all others
|
36
|
-
|
37
|
-
|
36
|
+
this.element.find('.collapse' + target).collapse('show');
|
37
|
+
this.element.find('.collapse:not(' + target + ')').collapse('hide');
|
38
38
|
}
|
39
39
|
else {
|
40
40
|
this.collapseAll()
|
@@ -6,6 +6,7 @@ module Hyrax::Controller
|
|
6
6
|
|
7
7
|
# Adds Hydra behaviors into the application controller
|
8
8
|
include Hydra::Controller::ControllerBehavior
|
9
|
+
helper_method :create_work_presenter
|
9
10
|
before_action :set_locale
|
10
11
|
end
|
11
12
|
|
@@ -14,6 +15,20 @@ module Hyrax::Controller
|
|
14
15
|
hyrax.dashboard_path
|
15
16
|
end
|
16
17
|
|
18
|
+
##
|
19
|
+
# @deprecated this helper is no longer used by Hyrax; if you need access to
|
20
|
+
# this presenter on every page, you may need to readd it manually.
|
21
|
+
#
|
22
|
+
# A presenter for selecting a work type to create this is needed here because
|
23
|
+
# the selector is in the header on every page.
|
24
|
+
def create_work_presenter
|
25
|
+
Deprecation.warn(self, "The `create_work_presenter` helper is deprecated " \
|
26
|
+
"for removal in Hyrax 3.0. The work selector has " \
|
27
|
+
"been removed the masthead in Hyrax 2.1.")
|
28
|
+
|
29
|
+
Hyrax::SelectTypeListPresenter.new(current_user)
|
30
|
+
end
|
31
|
+
|
17
32
|
# Ensure that the locale choice is persistent across requests
|
18
33
|
def default_url_options
|
19
34
|
super.merge(locale: I18n.locale)
|
@@ -192,7 +192,9 @@ module Hyrax
|
|
192
192
|
end
|
193
193
|
|
194
194
|
def curation_concern_from_search_results
|
195
|
-
|
195
|
+
search_params = params
|
196
|
+
search_params.delete :page
|
197
|
+
search_result_document(search_params)
|
196
198
|
end
|
197
199
|
|
198
200
|
# Only returns unsuppressed documents the user has read access to
|
@@ -257,6 +257,14 @@ module Hyrax
|
|
257
257
|
content_tag(:span, "", class: [Hyrax::ModelIcon.css_class_for(Collection), "collection-icon-search"])
|
258
258
|
end
|
259
259
|
|
260
|
+
def collection_title_by_id(id)
|
261
|
+
solr_docs = controller.repository.find(id).docs
|
262
|
+
return nil if solr_docs.empty?
|
263
|
+
solr_field = solr_docs.first[Solrizer.solr_name("title", :stored_searchable)]
|
264
|
+
return nil if solr_field.nil?
|
265
|
+
solr_field.first
|
266
|
+
end
|
267
|
+
|
260
268
|
private
|
261
269
|
|
262
270
|
def user_agent
|
@@ -12,10 +12,10 @@ class AttachFilesToWorkJob < Hyrax::ApplicationJob
|
|
12
12
|
metadata = visibility_attributes(work_attributes)
|
13
13
|
uploaded_files.each do |uploaded_file|
|
14
14
|
actor = Hyrax::Actors::FileSetActor.new(FileSet.create, user)
|
15
|
+
actor.file_set.permissions_attributes = work_permissions
|
15
16
|
actor.create_metadata(metadata)
|
16
17
|
actor.create_content(uploaded_file)
|
17
18
|
actor.attach_to_work(work)
|
18
|
-
actor.file_set.permissions_attributes = work_permissions
|
19
19
|
uploaded_file.update(file_set_uri: actor.file_set.uri)
|
20
20
|
end
|
21
21
|
end
|
@@ -82,12 +82,7 @@ module Hyrax
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def parent
|
85
|
-
|
86
|
-
fl: ActiveFedora.id_field)
|
87
|
-
.map { |x| x.fetch(ActiveFedora.id_field) }
|
88
|
-
@parent_presenter ||= Hyrax::PresenterFactory.build_for(ids: ids,
|
89
|
-
presenter_class: WorkShowPresenter,
|
90
|
-
presenter_args: current_ability).first
|
85
|
+
@parent_presenter ||= fetch_parent_presenter
|
91
86
|
end
|
92
87
|
|
93
88
|
def user_can_perform_any_action?
|
@@ -99,5 +94,14 @@ module Hyrax
|
|
99
94
|
def link_presenter_class
|
100
95
|
SingleUseLinkPresenter
|
101
96
|
end
|
97
|
+
|
98
|
+
def fetch_parent_presenter
|
99
|
+
ids = ActiveFedora::SolrService.query("{!field f=member_ids_ssim}#{id}",
|
100
|
+
fl: ActiveFedora.id_field)
|
101
|
+
.map { |x| x.fetch(ActiveFedora.id_field) }
|
102
|
+
Hyrax::PresenterFactory.build_for(ids: ids,
|
103
|
+
presenter_class: WorkShowPresenter,
|
104
|
+
presenter_args: current_ability).first
|
105
|
+
end
|
102
106
|
end
|
103
107
|
end
|
@@ -36,17 +36,17 @@ module Hyrax
|
|
36
36
|
@work_presenters ||= member_presenters(ordered_ids - file_set_ids, work_presenter_class)
|
37
37
|
end
|
38
38
|
|
39
|
-
|
39
|
+
# TODO: Extract this to ActiveFedora::Aggregations::ListSource
|
40
|
+
def ordered_ids
|
41
|
+
@ordered_ids ||= begin
|
42
|
+
ActiveFedora::SolrService.query("proxy_in_ssi:#{id}",
|
43
|
+
rows: 10_000,
|
44
|
+
fl: "ordered_targets_ssim")
|
45
|
+
.flat_map { |x| x.fetch("ordered_targets_ssim", []) }
|
46
|
+
end
|
47
|
+
end
|
40
48
|
|
41
|
-
|
42
|
-
def ordered_ids
|
43
|
-
@ordered_ids ||= begin
|
44
|
-
ActiveFedora::SolrService.query("proxy_in_ssi:#{id}",
|
45
|
-
rows: 10_000,
|
46
|
-
fl: "ordered_targets_ssim")
|
47
|
-
.flat_map { |x| x.fetch("ordered_targets_ssim", []) }
|
48
|
-
end
|
49
|
-
end
|
49
|
+
private
|
50
50
|
|
51
51
|
# These are the file sets that belong to this work, but not necessarily
|
52
52
|
# in order.
|
@@ -69,7 +69,7 @@ module Hyrax
|
|
69
69
|
return nil if representative_id.blank?
|
70
70
|
@representative_presenter ||=
|
71
71
|
begin
|
72
|
-
result =
|
72
|
+
result = member_presenters_for([representative_id]).first
|
73
73
|
return nil if result.try(:id) == id
|
74
74
|
if result.respond_to?(:representative_presenter)
|
75
75
|
result.representative_presenter
|
@@ -153,10 +153,22 @@ module Hyrax
|
|
153
153
|
solr_document.to_model
|
154
154
|
end
|
155
155
|
|
156
|
-
delegate :member_presenters, :file_set_presenters, :work_presenters, to: :member_presenter_factory
|
156
|
+
delegate :member_presenters, :ordered_ids, :file_set_presenters, :work_presenters, to: :member_presenter_factory
|
157
157
|
|
158
|
-
|
159
|
-
|
158
|
+
# @return [Array] list to display with Kaminari pagination
|
159
|
+
def list_of_item_ids_to_display
|
160
|
+
paginated_item_list(page_array: authorized_item_ids)
|
161
|
+
end
|
162
|
+
|
163
|
+
# @param [Array<String>] ids a list of ids to build presenters for
|
164
|
+
# @return [Array<presenter_class>] presenters for the array of ids (not filtered by class)
|
165
|
+
def member_presenters_for(an_array_of_ids)
|
166
|
+
member_presenters(an_array_of_ids)
|
167
|
+
end
|
168
|
+
|
169
|
+
# @return [Integer] total number of pages of viewable items
|
170
|
+
def total_pages
|
171
|
+
(total_items.to_f / rows_from_params.to_f).ceil
|
160
172
|
end
|
161
173
|
|
162
174
|
def manifest_url
|
@@ -194,6 +206,33 @@ module Hyrax
|
|
194
206
|
|
195
207
|
private
|
196
208
|
|
209
|
+
# list of item ids to display is based on ordered_ids
|
210
|
+
def authorized_item_ids
|
211
|
+
@member_item_list_ids ||= begin
|
212
|
+
items = ordered_ids
|
213
|
+
items.delete_if { |m| !current_ability.can?(:read, m) } if Flipflop.hide_private_items?
|
214
|
+
items
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
# Uses kaminari to paginate an array to avoid need for solr documents for items here
|
219
|
+
def paginated_item_list(page_array:)
|
220
|
+
Kaminari.paginate_array(page_array, total_count: page_array.size).page(current_page).per(rows_from_params)
|
221
|
+
end
|
222
|
+
|
223
|
+
def total_items
|
224
|
+
authorized_item_ids.size
|
225
|
+
end
|
226
|
+
|
227
|
+
def rows_from_params
|
228
|
+
request.params[:rows].nil? ? Hyrax.config.show_work_item_rows : request.params[:rows].to_i
|
229
|
+
end
|
230
|
+
|
231
|
+
def current_page
|
232
|
+
page = request.params[:page].nil? ? 1 : request.params[:page].to_i
|
233
|
+
page > total_pages ? total_pages : page
|
234
|
+
end
|
235
|
+
|
197
236
|
def manifest_helper
|
198
237
|
@manifest_helper ||= ManifestHelper.new(request.base_url)
|
199
238
|
end
|
@@ -8,7 +8,7 @@ module Hyrax
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def search_path(value)
|
11
|
-
Rails.application.routes.url_helpers.search_catalog_path(:"f[#{search_field}][]" => value)
|
11
|
+
Rails.application.routes.url_helpers.search_catalog_path(:"f[#{search_field}][]" => value, locale: I18n.locale)
|
12
12
|
end
|
13
13
|
|
14
14
|
def search_field
|
@@ -2,7 +2,8 @@ class Hyrax::CatalogSearchBuilder < Hyrax::SearchBuilder
|
|
2
2
|
self.default_processor_chain += [
|
3
3
|
:add_access_controls_to_solr_params,
|
4
4
|
:show_works_or_works_that_contain_files,
|
5
|
-
:show_only_active_records
|
5
|
+
:show_only_active_records,
|
6
|
+
:filter_collection_facet_for_access
|
6
7
|
]
|
7
8
|
|
8
9
|
# show both works that match the query and works that contain files that match the query
|
@@ -19,6 +20,18 @@ class Hyrax::CatalogSearchBuilder < Hyrax::SearchBuilder
|
|
19
20
|
solr_parameters[:fq] << '-suppressed_bsi:true'
|
20
21
|
end
|
21
22
|
|
23
|
+
# only return facet counts for collections that this user has access to see
|
24
|
+
def filter_collection_facet_for_access(solr_parameters)
|
25
|
+
return if current_ability.admin?
|
26
|
+
|
27
|
+
collection_ids = Hyrax::Collections::PermissionsService.collection_ids_for_view(ability: current_ability).map { |id| "^#{id}$" }
|
28
|
+
solr_parameters['f.member_of_collection_ids_ssim.facet.matches'] = if collection_ids.present?
|
29
|
+
collection_ids.join('|')
|
30
|
+
else
|
31
|
+
"^$"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
22
35
|
private
|
23
36
|
|
24
37
|
# the {!lucene} gives us the OR syntax
|
@@ -97,6 +97,19 @@ module Hyrax
|
|
97
97
|
source_ids_for_deposit(ability: ability, source_type: 'collection')
|
98
98
|
end
|
99
99
|
|
100
|
+
# @api public
|
101
|
+
#
|
102
|
+
# IDs of collections which the user can view.
|
103
|
+
#
|
104
|
+
# @param ability [Ability] the ability coming from cancan ability check
|
105
|
+
# @return [Array<String>] IDs of collections into which the user can view
|
106
|
+
# @note Several checks get the user's groups from the user's ability. The same values can be retrieved directly from a passed in ability.
|
107
|
+
def self.collection_ids_for_view(ability:)
|
108
|
+
collection_ids_for_user(ability: ability, access: [Hyrax::PermissionTemplateAccess::MANAGE,
|
109
|
+
Hyrax::PermissionTemplateAccess::DEPOSIT,
|
110
|
+
Hyrax::PermissionTemplateAccess::VIEW])
|
111
|
+
end
|
112
|
+
|
100
113
|
# @api public
|
101
114
|
#
|
102
115
|
# Determine if the given user has permissions to view the admin show page for at least one collection
|
@@ -1,5 +1,6 @@
|
|
1
1
|
<h2><%= t('.header') %></h2>
|
2
|
-
<%
|
2
|
+
<% array_of_ids = presenter.list_of_item_ids_to_display %>
|
3
|
+
<% members = presenter.member_presenters_for(array_of_ids) %>
|
3
4
|
<% if members.present? %>
|
4
5
|
<table class="table table-striped related-files">
|
5
6
|
<thead>
|
@@ -15,6 +16,13 @@
|
|
15
16
|
<%= render partial: 'member', collection: members %>
|
16
17
|
</tbody>
|
17
18
|
</table>
|
19
|
+
<div class="row">
|
20
|
+
<% if presenter.total_pages > 1 %>
|
21
|
+
<div class="row record-padding col-md-9">
|
22
|
+
<%= paginate array_of_ids, outer_window: 2, theme: 'blacklight', param_name: :page, route_set: main_app %>
|
23
|
+
</div><!-- /pager -->
|
24
|
+
<% end %>
|
25
|
+
</div>
|
18
26
|
<% elsif can? :edit, presenter.id %>
|
19
27
|
<div class="alert alert-warning" role="alert"><%= t('.empty', type: presenter.human_readable_type) %></div>
|
20
28
|
<% else %>
|
@@ -33,11 +33,12 @@
|
|
33
33
|
<div class="modal-footer">
|
34
34
|
<button type="button" class="btn btn-default" data-dismiss="modal"><%= t("hyrax.collection.select_form.close") %></button>
|
35
35
|
<% if user_collections.blank? %>
|
36
|
-
|
37
|
-
|
36
|
+
<% # TODO: Uncomment the following line when errors with adding works to a new collection are resolved. See Issue hyrax#3088 %>
|
37
|
+
<% # = render 'hyrax/dashboard/collections/button_create_collection', label: t("hyrax.collection.select_form.create") %>
|
38
38
|
<% else %>
|
39
39
|
<%= render 'hyrax/dashboard/collections/button_for_update_collection', label: t("hyrax.collection.select_form.update"), collection_id: 'collection_replace_id' %>
|
40
|
-
|
40
|
+
<% # TODO: Uncomment the following line when errors with adding works to a new collection are resolved. See Issue hyrax#3088 %>
|
41
|
+
<% # = render 'hyrax/dashboard/collections/button_create_collection', label: t("hyrax.collection.select_form.create_new") %>
|
41
42
|
<% end %>
|
42
43
|
</div>
|
43
44
|
</div><!-- /.modal-content -->
|
@@ -44,7 +44,7 @@ class CatalogController < ApplicationController
|
|
44
44
|
config.add_facet_field solr_name("based_near_label", :facetable), limit: 5
|
45
45
|
config.add_facet_field solr_name("publisher", :facetable), limit: 5
|
46
46
|
config.add_facet_field solr_name("file_format", :facetable), limit: 5
|
47
|
-
config.add_facet_field solr_name('
|
47
|
+
config.add_facet_field solr_name('member_of_collection_ids', :symbol), limit: 5, label: 'Collections', helper_method: :collection_title_by_id
|
48
48
|
|
49
49
|
# The generic_type isn't displayed on the facet list
|
50
50
|
# It's used to give a label to the filter that comes from the user profile
|
@@ -116,6 +116,10 @@ Hyrax.config do |config|
|
|
116
116
|
# The default is true.
|
117
117
|
# config.work_requires_files = true
|
118
118
|
|
119
|
+
# How many rows of items should appear on the work show view?
|
120
|
+
# The default is 10
|
121
|
+
# config.show_work_item_rows = 10
|
122
|
+
|
119
123
|
# Enable IIIF image service. This is required to use the
|
120
124
|
# UniversalViewer-ified show page
|
121
125
|
#
|
data/lib/hyrax/configuration.rb
CHANGED
@@ -340,6 +340,11 @@ module Hyrax
|
|
340
340
|
@work_requires_files
|
341
341
|
end
|
342
342
|
|
343
|
+
attr_writer :show_work_item_rows
|
344
|
+
def show_work_item_rows
|
345
|
+
@show_work_item_rows ||= 10 # rows on show view
|
346
|
+
end
|
347
|
+
|
343
348
|
attr_writer :batch_user_key
|
344
349
|
def batch_user_key
|
345
350
|
@batch_user_key ||= 'batchuser@example.com'
|
data/lib/hyrax/version.rb
CHANGED
@@ -28,4 +28,45 @@ RSpec.describe 'catalog searching', type: :feature do
|
|
28
28
|
expect(page).to have_content(collection.title.first)
|
29
29
|
end
|
30
30
|
end
|
31
|
+
|
32
|
+
context 'with public works and private collections', clean_repo: true do
|
33
|
+
let!(:collection) { create(:private_collection) }
|
34
|
+
|
35
|
+
let!(:jills_work) do
|
36
|
+
create(:public_work, title: ["Jill's Research"], keyword: ['jills_keyword'], member_of_collections: [collection])
|
37
|
+
end
|
38
|
+
|
39
|
+
it "hides collection facet values the user doesn't have access to view when performing a search" do
|
40
|
+
within('#search-form-header') do
|
41
|
+
fill_in('search-field-header', with: 'jills_keyword')
|
42
|
+
click_button('Go')
|
43
|
+
end
|
44
|
+
|
45
|
+
expect(page).to have_content('Search Results')
|
46
|
+
expect(page).to have_content(jills_work.title.first)
|
47
|
+
expect(page).not_to have_content(collection.title.first)
|
48
|
+
expect(page).not_to have_css('.blacklight-member_of_collection_ids_ssim')
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'as an admin' do
|
52
|
+
let(:admin_user) { create :admin }
|
53
|
+
|
54
|
+
before do
|
55
|
+
sign_in admin_user
|
56
|
+
visit '/'
|
57
|
+
end
|
58
|
+
|
59
|
+
it "shows collection facet values the user has access to view when performing a search" do
|
60
|
+
within('#search-form-header') do
|
61
|
+
fill_in('search-field-header', with: 'jills_keyword')
|
62
|
+
click_button('Go')
|
63
|
+
end
|
64
|
+
|
65
|
+
expect(page).to have_content('Search Results')
|
66
|
+
expect(page).to have_content(jills_work.title.first)
|
67
|
+
find('.blacklight-member_of_collection_ids_ssim').click
|
68
|
+
expect(page).to have_content(collection.title.first)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
31
72
|
end
|
@@ -366,4 +366,34 @@ RSpec.describe HyraxHelper, type: :helper do
|
|
366
366
|
expect(helper.banner_image).to eq(Hyrax.config.banner_image)
|
367
367
|
end
|
368
368
|
end
|
369
|
+
|
370
|
+
describe "#collection_title_by_id" do
|
371
|
+
let(:solr_doc) { double(id: "abcd12345") }
|
372
|
+
let(:bad_solr_doc) { double(id: "efgh67890") }
|
373
|
+
let(:solr_response) { double(docs: [solr_doc]) }
|
374
|
+
let(:bad_solr_response) { double(docs: [bad_solr_doc]) }
|
375
|
+
let(:empty_solr_response) { double(docs: []) }
|
376
|
+
let(:repository) { double }
|
377
|
+
|
378
|
+
before do
|
379
|
+
allow(controller).to receive(:repository).and_return(repository)
|
380
|
+
allow(solr_doc).to receive(:[]).with("title_tesim").and_return(["Collection of Awesomeness"])
|
381
|
+
allow(bad_solr_doc).to receive(:[]).with("title_tesim").and_return(nil)
|
382
|
+
allow(repository).to receive(:find).with("abcd12345").and_return(solr_response)
|
383
|
+
allow(repository).to receive(:find).with("efgh67890").and_return(bad_solr_response)
|
384
|
+
allow(repository).to receive(:find).with("bad-id").and_return(empty_solr_response)
|
385
|
+
end
|
386
|
+
|
387
|
+
it "returns the first title of the collection" do
|
388
|
+
expect(helper.collection_title_by_id("abcd12345")).to eq "Collection of Awesomeness"
|
389
|
+
end
|
390
|
+
|
391
|
+
it "returns nil if collection doesn't have title_tesim field" do
|
392
|
+
expect(helper.collection_title_by_id("efgh67890")).to eq nil
|
393
|
+
end
|
394
|
+
|
395
|
+
it "returns nil if collection not found" do
|
396
|
+
expect(helper.collection_title_by_id("bad-id")).to eq nil
|
397
|
+
end
|
398
|
+
end
|
369
399
|
end
|
@@ -72,6 +72,7 @@ RSpec.describe Hyrax::Configuration do
|
|
72
72
|
it { is_expected.to respond_to(:rights_statement_service_class=) }
|
73
73
|
it { is_expected.to respond_to(:redis_namespace) }
|
74
74
|
it { is_expected.to respond_to(:subject_prefix) }
|
75
|
+
it { is_expected.to respond_to(:show_work_item_rows) }
|
75
76
|
it { is_expected.to respond_to(:translate_id_to_uri) }
|
76
77
|
it { is_expected.to respond_to(:translate_uri_to_id) }
|
77
78
|
it { is_expected.to respond_to(:upload_path) }
|
@@ -68,7 +68,7 @@ RSpec.describe Hyrax::AdminSetPresenter do
|
|
68
68
|
|
69
69
|
subject { presenter.show_path }
|
70
70
|
|
71
|
-
it { is_expected.to eq "/admin/admin_sets/#{admin_set.id}" }
|
71
|
+
it { is_expected.to eq "/admin/admin_sets/#{admin_set.id}?locale=en" }
|
72
72
|
end
|
73
73
|
|
74
74
|
describe '#managed_access' do
|
@@ -357,7 +357,7 @@ RSpec.describe Hyrax::CollectionPresenter do
|
|
357
357
|
describe '#show_path' do
|
358
358
|
subject { presenter.show_path }
|
359
359
|
|
360
|
-
it { is_expected.to eq "/dashboard/collections/#{solr_doc.id}" }
|
360
|
+
it { is_expected.to eq "/dashboard/collections/#{solr_doc.id}?locale=en" }
|
361
361
|
end
|
362
362
|
|
363
363
|
describe "banner_file" do
|
@@ -30,6 +30,8 @@ RSpec.describe Hyrax::WorkShowPresenter do
|
|
30
30
|
it { is_expected.to delegate_method(:resource_type).to(:solr_document) }
|
31
31
|
it { is_expected.to delegate_method(:keyword).to(:solr_document) }
|
32
32
|
it { is_expected.to delegate_method(:itemtype).to(:solr_document) }
|
33
|
+
it { is_expected.to delegate_method(:member_presenters).to(:member_presenter_factory) }
|
34
|
+
it { is_expected.to delegate_method(:ordered_ids).to(:member_presenter_factory) }
|
33
35
|
|
34
36
|
describe "#model_name" do
|
35
37
|
subject { presenter.model_name }
|
@@ -224,13 +226,86 @@ RSpec.describe Hyrax::WorkShowPresenter do
|
|
224
226
|
end
|
225
227
|
end
|
226
228
|
|
227
|
-
describe "
|
229
|
+
describe "#member_presenters_for" do
|
228
230
|
let(:obj) { create(:work_with_file_and_work) }
|
229
231
|
let(:attributes) { obj.to_solr }
|
230
|
-
let(:
|
232
|
+
let(:items) { presenter.ordered_ids }
|
233
|
+
let(:subject) { presenter.member_presenters_for(items) }
|
231
234
|
|
232
|
-
it
|
233
|
-
expect(
|
235
|
+
it "returns appropriate classes for each item" do
|
236
|
+
expect(subject.size).to eq 2
|
237
|
+
expect(subject.first).to be_instance_of(Hyrax::FileSetPresenter)
|
238
|
+
expect(subject.last).to be_instance_of(described_class)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
describe "#list_of_item_ids_to_display" do
|
243
|
+
let(:subject) { presenter.list_of_item_ids_to_display }
|
244
|
+
let(:items_list) { ['item0', 'item1', 'item2', 'item3', 'item4', 'item5', 'item6', 'item7', 'item8', 'item9'] }
|
245
|
+
let(:rows) { 10 }
|
246
|
+
let(:page) { 1 }
|
247
|
+
let(:ability) { double "Ability" }
|
248
|
+
let(:current_ability) { ability }
|
249
|
+
|
250
|
+
before do
|
251
|
+
allow(presenter).to receive(:ordered_ids).and_return(items_list)
|
252
|
+
allow(current_ability).to receive(:can?).with(:read, 'item0').and_return true
|
253
|
+
allow(current_ability).to receive(:can?).with(:read, 'item1').and_return false
|
254
|
+
allow(current_ability).to receive(:can?).with(:read, 'item2').and_return true
|
255
|
+
allow(current_ability).to receive(:can?).with(:read, 'item3').and_return false
|
256
|
+
allow(current_ability).to receive(:can?).with(:read, 'item4').and_return true
|
257
|
+
allow(current_ability).to receive(:can?).with(:read, 'item5').and_return true
|
258
|
+
allow(current_ability).to receive(:can?).with(:read, 'item6').and_return false
|
259
|
+
allow(current_ability).to receive(:can?).with(:read, 'item7').and_return true
|
260
|
+
allow(current_ability).to receive(:can?).with(:read, 'item8').and_return false
|
261
|
+
allow(current_ability).to receive(:can?).with(:read, 'item9').and_return true
|
262
|
+
allow(presenter).to receive(:rows_from_params).and_return(rows)
|
263
|
+
allow(presenter).to receive(:current_page).and_return(page)
|
264
|
+
allow(Flipflop).to receive(:hide_private_items?).and_return(answer)
|
265
|
+
end
|
266
|
+
|
267
|
+
context 'when hiding private items' do
|
268
|
+
let(:answer) { true }
|
269
|
+
|
270
|
+
it "returns viewable items" do
|
271
|
+
expect(subject.size).to eq 6
|
272
|
+
expect(subject).to be_instance_of(Kaminari::PaginatableArray)
|
273
|
+
expect(subject).to include("item0", "item2", "item4", "item5", "item7", "item9")
|
274
|
+
end
|
275
|
+
end
|
276
|
+
context 'when including private items' do
|
277
|
+
let(:answer) { false }
|
278
|
+
|
279
|
+
it "returns appropriate items" do
|
280
|
+
expect(subject.size).to eq 10
|
281
|
+
expect(subject).to be_instance_of(Kaminari::PaginatableArray)
|
282
|
+
expect(subject).to eq(items_list)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
context 'with pagination' do
|
286
|
+
let(:rows) { 3 }
|
287
|
+
let(:page) { 2 }
|
288
|
+
|
289
|
+
let(:answer) { true }
|
290
|
+
it 'partitions the item list and excluding hidden items' do
|
291
|
+
expect(subject).to eq(['item5', 'item7', 'item9'])
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
describe "#total_pages" do
|
297
|
+
let(:subject) { presenter.total_pages }
|
298
|
+
let(:items) { 17 }
|
299
|
+
let(:rows) { 4 }
|
300
|
+
|
301
|
+
before do
|
302
|
+
allow(Flipflop).to receive(:hide_private_items?).and_return(false)
|
303
|
+
allow(presenter).to receive(:total_items).and_return(items)
|
304
|
+
allow(presenter).to receive(:rows_from_params).and_return(rows)
|
305
|
+
end
|
306
|
+
|
307
|
+
it 'calculates number of pages from items and rows' do
|
308
|
+
expect(subject).to eq(5)
|
234
309
|
end
|
235
310
|
end
|
236
311
|
|
@@ -11,8 +11,8 @@ RSpec.describe Hyrax::Renderers::FacetedAttributeRenderer do
|
|
11
11
|
%(
|
12
12
|
<tr><th>Name</th>
|
13
13
|
<td><ul class='tabular'>
|
14
|
-
<li class="attribute attribute-name"><a href="/catalog?f%5Bname_sim%5D%5B%5D=Bob">Bob</a></li>
|
15
|
-
<li class="attribute attribute-name"><a href="/catalog?f%5Bname_sim%5D%5B%5D=Jessica">Jessica</a></li>
|
14
|
+
<li class="attribute attribute-name"><a href="/catalog?f%5Bname_sim%5D%5B%5D=Bob&locale=en">Bob</a></li>
|
15
|
+
<li class="attribute attribute-name"><a href="/catalog?f%5Bname_sim%5D%5B%5D=Jessica&locale=en">Jessica</a></li>
|
16
16
|
</ul></td></tr>
|
17
17
|
)
|
18
18
|
end
|
@@ -28,7 +28,7 @@ RSpec.describe Hyrax::Renderers::FacetedAttributeRenderer do
|
|
28
28
|
let(:rendered_link_query) { URI.parse(rendered_link['href']).query }
|
29
29
|
|
30
30
|
it "escapes content properly" do
|
31
|
-
expect(rendered_link_query).to eq "#{CGI.escape('f[name_sim][]')}=#{CGI.escape('John & Bob')}"
|
31
|
+
expect(rendered_link_query).to eq "#{CGI.escape('f[name_sim][]')}=#{CGI.escape('John & Bob')}&locale=en"
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
@@ -10,8 +10,8 @@ RSpec.describe Hyrax::Renderers::LinkedAttributeRenderer do
|
|
10
10
|
let(:tr_content) do
|
11
11
|
"<tr><th>Name</th>\n" \
|
12
12
|
"<td><ul class='tabular'>" \
|
13
|
-
"<li class=\"attribute attribute-name\"><a href=\"/catalog?q=Bob&search_field=name\">Bob</a></li>\n" \
|
14
|
-
"<li class=\"attribute attribute-name\"><a href=\"/catalog?q=Jessica&search_field=name\">Jessica</a></li>\n" \
|
13
|
+
"<li class=\"attribute attribute-name\"><a href=\"/catalog?locale=en&q=Bob&search_field=name\">Bob</a></li>\n" \
|
14
|
+
"<li class=\"attribute attribute-name\"><a href=\"/catalog?locale=en&q=Jessica&search_field=name\">Jessica</a></li>\n" \
|
15
15
|
"</ul></td></tr>"
|
16
16
|
end
|
17
17
|
|
@@ -48,4 +48,39 @@ RSpec.describe Hyrax::CatalogSearchBuilder do
|
|
48
48
|
expect(solr_params[:fq]).to eq ["-suppressed_bsi:true"]
|
49
49
|
end
|
50
50
|
end
|
51
|
+
|
52
|
+
describe "#filter_collection_facet_for_access" do
|
53
|
+
let(:user) { build(:user) }
|
54
|
+
let(:ability) { Ability.new(user) }
|
55
|
+
let(:context) { double(current_ability: ability) }
|
56
|
+
|
57
|
+
subject { builder.filter_collection_facet_for_access(solr_params) }
|
58
|
+
|
59
|
+
context 'with an admin' do
|
60
|
+
let(:user) { build(:admin) }
|
61
|
+
|
62
|
+
it "does nothing if user is an admin" do
|
63
|
+
subject
|
64
|
+
expect(solr_params['f.member_of_collection_ids_ssim.facet.matches']).to be_blank
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'when the user has view access to collections' do
|
69
|
+
let(:collection_ids) { ['abcd12345', 'efgh67890'] }
|
70
|
+
|
71
|
+
before do
|
72
|
+
allow(Hyrax::Collections::PermissionsService).to receive(:collection_ids_for_view).with(ability: ability).and_return(collection_ids)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "includes a regex of the ids of collections" do
|
76
|
+
subject
|
77
|
+
expect(solr_params['f.member_of_collection_ids_ssim.facet.matches']).to eq '^abcd12345$|^efgh67890$'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it "includes an empty regex when user doesn't have access to view any collections" do
|
82
|
+
subject
|
83
|
+
expect(solr_params['f.member_of_collection_ids_ssim.facet.matches']).to eq '^$'
|
84
|
+
end
|
85
|
+
end
|
51
86
|
end
|
@@ -299,6 +299,20 @@ RSpec.describe Hyrax::Collections::PermissionsService do
|
|
299
299
|
end
|
300
300
|
end
|
301
301
|
|
302
|
+
describe '.collection_ids_for_view' do
|
303
|
+
it 'returns collection ids where user has view access' do
|
304
|
+
expect(described_class.collection_ids_for_view(ability: ability)).to match_array [col_du.id, col_dg.id, col_mu.id, col_mg.id, col_vu.id, col_vg.id]
|
305
|
+
end
|
306
|
+
|
307
|
+
context 'when user has no access' do
|
308
|
+
let(:ability) { Ability.new(user2) }
|
309
|
+
|
310
|
+
it 'returns empty array' do
|
311
|
+
expect(described_class.collection_ids_for_view(ability: ability)).to match_array []
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
302
316
|
describe '.can_manage_any_collection?' do
|
303
317
|
it 'returns true when user has manage access to at least one collection' do
|
304
318
|
expect(described_class.can_manage_any_collection?(ability: ability)).to be true
|
@@ -1,11 +1,17 @@
|
|
1
1
|
RSpec.describe 'hyrax/base/_items.html.erb', type: :view do
|
2
2
|
let(:ability) { double }
|
3
|
-
let(:
|
3
|
+
let(:request) { double "request", params: params }
|
4
|
+
let(:params) { ActionController::Parameters.new(rows: 10) }
|
4
5
|
|
5
6
|
context 'when children are not present' do
|
6
|
-
let(:
|
7
|
+
let(:member_list) { [] }
|
8
|
+
let(:presenter) { double(:presenter, list_of_items_to_display: member_list, member_presenters_for: member_list, id: 'the-id', human_readable_type: 'Thing') }
|
7
9
|
|
8
|
-
|
10
|
+
before do
|
11
|
+
expect(presenter).to receive(:list_of_item_ids_to_display).and_return(member_list)
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'and the current user can edit the presenter' do
|
9
15
|
it 'renders an alert' do
|
10
16
|
expect(view).to receive(:can?).with(:edit, presenter.id).and_return(true)
|
11
17
|
render 'hyrax/base/items', presenter: presenter
|
@@ -25,35 +31,23 @@ RSpec.describe 'hyrax/base/_items.html.erb', type: :view do
|
|
25
31
|
let(:child1) { double('Thing1', id: 'Thing 1', title: 'Title 1') }
|
26
32
|
let(:child2) { double('Thing2', id: 'Thing 2', title: 'Title 2') }
|
27
33
|
let(:child3) { double('Thing3', id: 'Thing 3', title: 'Title 3') }
|
28
|
-
let(:
|
29
|
-
let(:authorized_presenters) { [child1, child3] }
|
34
|
+
let(:member_list) { [child1, child2, child3] }
|
30
35
|
let(:solr_document) { double('Solr Doc', id: 'the-id') }
|
31
36
|
let(:presenter) { Hyrax::WorkShowPresenter.new(solr_document, ability, request) }
|
32
37
|
|
33
38
|
before do
|
34
39
|
stub_template 'hyrax/base/_member.html.erb' => '<%= member %>'
|
35
40
|
expect(Flipflop).to receive(:hide_private_items?).and_return(:flipflop)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
context 'and hide_private_items is on' do
|
43
|
-
let(:flip_flop) { true }
|
44
|
-
|
45
|
-
it "displays only authorized children" do
|
46
|
-
render 'hyrax/base/items', presenter: presenter
|
47
|
-
expect(rendered).to have_css('tbody', text: authorized_presenters.join)
|
48
|
-
end
|
41
|
+
allow(presenter).to receive(:list_of_item_ids_to_display).and_return(member_list)
|
42
|
+
allow(presenter).to receive(:member_presenters_for).with(member_list).and_return(member_list)
|
43
|
+
allow(ability).to receive(:can?).with(:read, child1.id).and_return true
|
44
|
+
allow(ability).to receive(:can?).with(:read, child2.id).and_return false
|
45
|
+
allow(ability).to receive(:can?).with(:read, child3.id).and_return true
|
49
46
|
end
|
50
|
-
context 'and hide_private_items is off' do
|
51
|
-
let(:flip_flop) { false }
|
52
47
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
end
|
48
|
+
it "displays children" do
|
49
|
+
render 'hyrax/base/items', presenter: presenter
|
50
|
+
expect(rendered).to have_css('tbody')
|
57
51
|
end
|
58
52
|
end
|
59
53
|
end
|
@@ -45,7 +45,7 @@ RSpec.describe 'hyrax/my/collections/_list_collections.html.erb', type: :view do
|
|
45
45
|
expect(rendered).to have_selector("tr#document_#{id}")
|
46
46
|
check_tr_data_attributes
|
47
47
|
expect(rendered).to have_selector("tr[data-post-delete-url='/dashboard/collections/#{id}']")
|
48
|
-
expect(rendered).to have_link 'Collection Title', href: hyrax.dashboard_collection_path(id)
|
48
|
+
expect(rendered).to have_link 'Collection Title', href: hyrax.dashboard_collection_path(id, locale: I18n.locale)
|
49
49
|
expect(rendered).to have_link 'Edit collection', href: hyrax.edit_dashboard_collection_path(id)
|
50
50
|
expect(rendered).to have_link 'Delete collection'
|
51
51
|
expect(rendered).to have_link 'Add to collection'
|
data/template.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hyrax
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.0.
|
4
|
+
version: 2.1.0.rc4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Coyne
|
@@ -14,7 +14,7 @@ authors:
|
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date: 2018-05-
|
17
|
+
date: 2018-05-30 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: rails
|