blacklight 3.6.1.1 → 3.7.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.
Files changed (32) hide show
  1. data/VERSION +1 -1
  2. data/app/controllers/bookmarks_controller.rb +28 -46
  3. data/app/helpers/blacklight/blacklight_helper_behavior.rb +4 -11
  4. data/app/helpers/blacklight/facets_helper_behavior.rb +57 -4
  5. data/app/helpers/blacklight/render_constraints_helper_behavior.rb +4 -1
  6. data/app/helpers/blacklight/search_history_constraints_helper_behavior.rb +5 -3
  7. data/app/views/_user_util_links.html.erb +8 -7
  8. data/app/views/bookmarks/index.html.erb +1 -1
  9. data/app/views/catalog/_bookmark_control.html.erb +2 -2
  10. data/lib/blacklight/configuration.rb +14 -1
  11. data/lib/blacklight/configuration/facet_field.rb +14 -0
  12. data/lib/blacklight/controller.rb +44 -7
  13. data/lib/blacklight/routes.rb +1 -10
  14. data/lib/blacklight/solr_helper.rb +60 -17
  15. data/lib/generators/blacklight/blacklight_generator.rb +1 -0
  16. data/lib/generators/blacklight/templates/catalog_controller.rb +11 -6
  17. data/test_support/bin/test.sh +1 -0
  18. data/test_support/features/bookmarks.feature +9 -19
  19. data/test_support/spec/controllers/application_controller_spec.rb +1 -0
  20. data/test_support/spec/controllers/bookmarks_controller_spec.rb +48 -0
  21. data/test_support/spec/controllers/catalog_controller_spec.rb +2 -1
  22. data/test_support/spec/controllers/search_history_controller_spec.rb +2 -0
  23. data/test_support/spec/helpers/blacklight_helper_spec.rb +1 -2
  24. data/test_support/spec/helpers/facets_helper_spec.rb +91 -4
  25. data/test_support/spec/helpers/search_history_constraints_helper_spec.rb +3 -0
  26. data/test_support/spec/lib/solr_helper_spec.rb +56 -8
  27. metadata +6 -9
  28. data/app/controllers/folder_controller.rb +0 -54
  29. data/app/views/catalog/_folder_control.html.erb +0 -12
  30. data/test_support/features/folder.feature +0 -67
  31. data/test_support/features/step_definitions/folder_steps.rb +0 -27
  32. data/test_support/spec/controllers/folder_controller_spec.rb +0 -47
@@ -24,7 +24,7 @@ module Blacklight
24
24
  end
25
25
 
26
26
  def default_route_sets
27
- [:bookmarks, :folders, :search_history, :saved_searches, :catalog, :solr_document, :feedback]
27
+ [:bookmarks, :search_history, :saved_searches, :catalog, :solr_document, :feedback]
28
28
  end
29
29
 
30
30
  module RouteSets
@@ -35,15 +35,6 @@ module Blacklight
35
35
  end
36
36
  end
37
37
 
38
-
39
- def folders
40
- add_routes do |options|
41
- match "folder/clear", :to => "folder#clear", :as => "clear_folder"
42
- match "folder/destroy", :to => "folder#destroy"
43
- resources :folder, :only => [:index, :update, :destroy]
44
- end
45
- end
46
-
47
38
  def search_history
48
39
  add_routes do |options|
49
40
  match "search_history", :to => "search_history#index", :as => "search_history"
@@ -244,12 +244,19 @@ module Blacklight::SolrHelper
244
244
  ##
245
245
  # Add any existing facet limits, stored in app-level HTTP query
246
246
  # as :f, to solr as appropriate :fq query.
247
- def add_facet_fq_to_solr(solr_parameters, user_params)
247
+ def add_facet_fq_to_solr(solr_parameters, user_params)
248
+
249
+ # convert a String value into an Array
250
+ if solr_parameters[:fq].is_a? String
251
+ solr_parameters[:fq] = [solr_parameters[:fq]]
252
+ end
253
+
248
254
  # :fq, map from :f.
249
255
  if ( user_params[:f])
250
256
  f_request_params = user_params[:f]
251
257
 
252
258
  solr_parameters[:fq] ||= []
259
+
253
260
  f_request_params.each_pair do |facet_field, value_list|
254
261
  Array(value_list).each do |value|
255
262
  solr_parameters[:fq] << facet_value_to_fq_string(facet_field, value)
@@ -261,18 +268,30 @@ module Blacklight::SolrHelper
261
268
  ##
262
269
  # Convert a facet/value pair into a solr fq parameter
263
270
  def facet_value_to_fq_string(facet_field, value)
264
- case
265
- when (value.is_a?(TrueClass) or value.is_a?(FalseClass) or value == 'true' or value == 'false')
266
- "#{facet_field}:#{value}"
267
- when (value.is_a?(Integer) or (value.to_i.to_s == value if value.respond_to? :to_i))
268
- "#{facet_field}:#{value}"
269
- when (value.is_a?(Float) or (value.to_f.to_s == value if value.respond_to? :to_f))
270
- "#{facet_field}:#{value}"
271
+ facet_config = blacklight_config.facet_fields[facet_field]
272
+
273
+ local_params = []
274
+ local_params << "tag=#{facet_config.tag}" if facet_config and facet_config.tag
275
+
276
+ prefix = ""
277
+ prefix = "{!#{local_params.join(" ")}}" unless local_params.empty?
278
+
279
+ fq = case
280
+ when (facet_config and facet_config.query)
281
+ facet_config.query[value][:fq]
282
+ when (facet_config and facet_config.date),
283
+ (value.is_a?(TrueClass) or value.is_a?(FalseClass) or value == 'true' or value == 'false'),
284
+ (value.is_a?(Integer) or (value.to_i.to_s == value if value.respond_to? :to_i)),
285
+ (value.is_a?(Float) or (value.to_f.to_s == value if value.respond_to? :to_f))
286
+ (value.is_a?(DateTime) or value.is_a?(Date) or value.is_a?(Time))
287
+ "#{prefix}#{facet_field}:#{value}"
271
288
  when value.is_a?(Range)
272
- "#{facet_field}:[#{value.first} TO #{value.last}]"
289
+ "#{prefix}#{facet_field}:[#{value.first} TO #{value.last}]"
273
290
  else
274
- "{!raw f=#{facet_field}}#{value}"
291
+ "{!raw f=#{facet_field}#{(" " + local_params.join(" ")) unless local_params.empty?}}#{value}"
275
292
  end
293
+
294
+
276
295
  end
277
296
 
278
297
  ##
@@ -290,14 +309,38 @@ module Blacklight::SolrHelper
290
309
  solr_parameters[:"facet.field"] ||= []
291
310
  solr_parameters[:"facet.field"].concat( [user_params["facet.field"], user_params["facets"]].flatten.compact ).uniq!
292
311
  end
293
-
294
- # Support facet paging and 'more'
295
- # links, by sending a facet.limit one more than what we
296
- # want to page at, according to configured facet limits.
312
+
313
+
314
+ if blacklight_config.add_facet_fields_to_solr_request
315
+ solr_parameters[:'facet.field'] ||= []
316
+ solr_parameters[:'facet.field'] += blacklight_config.facet_fields_to_add_to_solr
317
+
318
+ if blacklight_config.facet_fields.any? { |k,v| v[:query] }
319
+ solr_parameters[:'facet.query'] ||= []
320
+ end
321
+ end
322
+
297
323
  blacklight_config.facet_fields.each do |field_name, facet|
298
- next unless (limit = facet_limit_for(field_name))
299
-
300
- solr_parameters[:"f.#{field_name}.facet.limit"] = (limit + 1)
324
+
325
+ if blacklight_config.add_facet_fields_to_solr_request
326
+ case
327
+ when facet.query
328
+ solr_parameters[:'facet.query'] += facet.query.map { |k, x| x[:fq] }
329
+
330
+ when facet.ex
331
+ idx = solr_parameters[:'facet.field'].index(facet.field)
332
+ solr_parameters[:'facet.field'][idx] = "{!ex=#{facet.ex}}#{solr_parameters[:'facet.field'][idx]}" unless idx.nil?
333
+ end
334
+
335
+ if facet.sort
336
+ solr_parameters[:"f.#{facet.field}.facet.sort"] = facet.sort
337
+ end
338
+ end
339
+
340
+ # Support facet paging and 'more'
341
+ # links, by sending a facet.limit one more than what we
342
+ # want to page at, according to configured facet limits.
343
+ solr_parameters[:"f.#{facet.field}.facet.limit"] = (facet_limit_for(field_name) + 1) if facet_limit_for(field_name)
301
344
  end
302
345
  end
303
346
 
@@ -69,6 +69,7 @@ EOF
69
69
  def generate_devise_assets
70
70
  if options[:devise]
71
71
  gem "devise"
72
+ gem "devise-guests"
72
73
  run "bundle install"
73
74
  generate "devise:install"
74
75
  generate "devise", model_name.classify
@@ -51,21 +51,26 @@ class CatalogController < ApplicationController
51
51
  #
52
52
  # :show may be set to false if you don't want the facet to be drawn in the
53
53
  # facet bar
54
- config.add_facet_field 'format', :label => 'Format'
55
- config.add_facet_field 'pub_date', :label => 'Publication Year'
54
+ config.add_facet_field 'format', :label => 'Format'
55
+ config.add_facet_field 'pub_date', :label => 'Publication Year', :single => true
56
56
  config.add_facet_field 'subject_topic_facet', :label => 'Topic', :limit => 20
57
57
  config.add_facet_field 'language_facet', :label => 'Language', :limit => true
58
58
  config.add_facet_field 'lc_1letter_facet', :label => 'Call Number'
59
59
  config.add_facet_field 'subject_geo_facet', :label => 'Region'
60
60
  config.add_facet_field 'subject_era_facet', :label => 'Era'
61
61
 
62
+
63
+ config.add_facet_field 'example_query_facet_field', :label => 'Publish Date', :query => {
64
+ :years_5 => { :label => 'within 5 Years', :fq => "pub_date:[#{Time.now.year - 5 } TO *]" },
65
+ :years_10 => { :label => 'within 10 Years', :fq => "pub_date:[#{Time.now.year - 10 } TO *]" },
66
+ :years_25 => { :label => 'within 25 Years', :fq => "pub_date:[#{Time.now.year - 25 } TO *]" }
67
+ }
68
+
69
+
62
70
  # Have BL send all facet field names to Solr, which has been the default
63
71
  # previously. Simply remove these lines if you'd rather use Solr request
64
72
  # handler defaults, or have no facets.
65
- config.default_solr_params[:'facet.field'] = config.facet_fields.keys
66
- #use this instead if you don't want to query facets marked :show=>false
67
- #config.default_solr_params[:'facet.field'] = config.facet_fields.select{ |k, v| v[:show] != false}.keys
68
-
73
+ config.add_facet_fields_to_solr_request!
69
74
 
70
75
  # solr fields to be displayed in the index (search results) view
71
76
  # The ordering of the field names is the order of the display
@@ -110,6 +110,7 @@ end
110
110
 
111
111
  gem 'jettywrapper', '>= 1.2.0'
112
112
  gem \"devise\"
113
+ gem \"devise-guests\"
113
114
  " >> Gemfile
114
115
 
115
116
  bundle install
@@ -16,11 +16,7 @@ Feature: Bookmarks
16
16
  Given I am logged in as "user1"
17
17
  When I go to the bookmarks page
18
18
  Then I should see "You have no bookmarks"
19
-
20
- Scenario: Bookmarks not logged in
21
- When I go to the bookmarks page
22
- Then I should see "Sign in"
23
-
19
+
24
20
  Scenario: User Has Bookmarks
25
21
  Given I am logged in as "user1"
26
22
  And "user1" has bookmarked an item with title "foo bar"
@@ -72,17 +68,11 @@ Feature: Bookmarks
72
68
  And I press "Remove bookmark"
73
69
  And I should see "Successfully removed bookmark"
74
70
 
75
- Scenario: Adding bookmarks from Folder
76
- Given I am logged in as "user1"
77
- And I have record 2007020969 in my folder
78
- And I have record 2008308175 in my folder
79
- And I follow "Selected Items"
80
- And I press "Add to Bookmarks"
81
- Then I should see "Successfully added bookmarks."
82
-
83
- Scenario: Adding bookmark from Folder
84
- Given I am logged in as "user1"
85
- And I have record 2007020969 in my folder
86
- And I follow "Selected Items"
87
- And I press "Add to Bookmarks"
88
- Then I should see "Successfully added bookmark."
71
+ Scenario: Adding bookmarks after a user logs in
72
+ Given I am on the document page for id 2007020969
73
+ Then I should see a "Bookmark" button
74
+ And I press "Bookmark"
75
+ And I am logged in as "user1"
76
+ When I go to the bookmarks page
77
+ Then I should see a "Remove" button
78
+
@@ -1,6 +1,7 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
3
3
  describe ApplicationController do
4
+ include Devise::TestHelpers
4
5
 
5
6
  # HEAD CONTENT
6
7
  describe "head content from variables" do
@@ -0,0 +1,48 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe BookmarksController do
4
+ include Devise::TestHelpers
5
+ let :user do
6
+ User.create :email => 'mods_asset@example.com', :password => 'modsasset'
7
+ end
8
+
9
+ before(:each) do
10
+ request.env["HTTP_REFERER"] = "/"
11
+
12
+ sign_in user
13
+ end
14
+
15
+ it "should create bookmarks" do
16
+ post "create", :bookmark => { :document_id => 'a' }
17
+ Bookmark.last.document_id.should == 'a'
18
+ end
19
+
20
+ it "should create multiple bookmarks" do
21
+ post "create", :bookmarks => [
22
+ { :document_id => 'a' },
23
+ { :document_id => 'b' }
24
+ ]
25
+ Bookmark.count.should == 2
26
+ end
27
+
28
+ it "should not create duplicate bookmarks" do
29
+ post "create", :bookmark => { :document_id => 'a' }
30
+ post "create", :bookmark => { :document_id => 'b' }
31
+ post "create", :bookmark => { :document_id => 'a' }
32
+ Bookmark.count.should == 2
33
+ end
34
+
35
+ it "should delete bookmarks" do
36
+ post "create", :bookmark => { :document_id => 'a' }
37
+ Bookmark.count.should == 1
38
+ delete "destroy", :id => 'a'
39
+ Bookmark.count.should == 0
40
+ end
41
+
42
+ it "should clear bookmarks" do
43
+ post "create", :bookmark => { :document_id => 'a' }
44
+ post "create", :bookmark => { :document_id => 'b' }
45
+ delete "clear"
46
+ Bookmark.count.should == 0
47
+ end
48
+ end
@@ -4,6 +4,7 @@ require 'rubygems'
4
4
  require 'marc'
5
5
 
6
6
  describe CatalogController do
7
+ include Devise::TestHelpers
7
8
  #=begin
8
9
  # ROUTES and MAPPING
9
10
  describe "Paths Generated by Custom Routes:" do
@@ -489,7 +490,7 @@ describe CatalogController do
489
490
  controller.stub(:has_user_authentication_provider?) { false }
490
491
  @mock_response = mock()
491
492
  @mock_document = mock()
492
- @mock_response.stub(:docs => [], :total => 1, :facets => [], :facet_by_field_name => nil)
493
+ @mock_response.stub(:docs => [], :total => 1, :facets => [], :facet_queries => {}, :facet_by_field_name => nil)
493
494
  @mock_document = mock()
494
495
  controller.stub(:find => @mock_response,
495
496
  :get_single_doc_via_search => @mock_document)
@@ -2,6 +2,8 @@
2
2
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
3
3
 
4
4
  describe SearchHistoryController do
5
+ include Devise::TestHelpers
6
+
5
7
  describe "index" do
6
8
  before(:all) do
7
9
  @one = Search.create
@@ -66,6 +66,7 @@ end
66
66
  describe BlacklightHelper do
67
67
  include ERB::Util
68
68
  include BlacklightHelper
69
+ include Devise::TestHelpers
69
70
  def blacklight_config
70
71
  @config ||= Blacklight::Configuration.new.configure do |config|
71
72
  config.show.html_title = "title_display"
@@ -356,14 +357,12 @@ describe BlacklightHelper do
356
357
  it "should render partials" do
357
358
  response = helper.render_index_doc_actions(@document)
358
359
  response.should have_selector(".bookmark_toggle")
359
- response.should have_selector(".folder_toggle")
360
360
  end
361
361
  end
362
362
  describe "render_show_doc_actions" do
363
363
  it "should render partials" do
364
364
  response = helper.render_show_doc_actions(@document)
365
365
  response.should have_selector(".bookmark_toggle")
366
- response.should have_selector(".folder_toggle")
367
366
  end
368
367
  end
369
368
  end
@@ -1,6 +1,11 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
  describe FacetsHelper do
3
+ let(:blacklight_config) { Blacklight::Configuration.new }
3
4
 
5
+ before(:each) do
6
+ helper.stub(:blacklight_config).and_return blacklight_config
7
+ end
8
+
4
9
  describe "should_render_facet?" do
5
10
  before do
6
11
  @config = Blacklight::Configuration.new do |config|
@@ -27,15 +32,64 @@ describe FacetsHelper do
27
32
 
28
33
  describe "facet_by_field_name" do
29
34
  it "should retrieve the facet from the response given a string" do
30
- a = mock(:name => 'a', :items => [1,2])
35
+ facet_config = mock(:query => nil)
36
+ facet_field = mock()
37
+ helper.should_receive(:facet_configuration_for_field).with(anything()).and_return(facet_config)
31
38
 
32
39
  @response = mock()
33
- @response.should_receive(:facet_by_field_name).with('a') { a }
40
+ @response.should_receive(:facet_by_field_name).with('a').and_return(facet_field)
41
+
42
+ helper.facet_by_field_name('a').should == facet_field
43
+ end
44
+
45
+ it "should also work for facet query fields" do
46
+ facet_config = mock(:query => {})
47
+ helper.should_receive(:facet_configuration_for_field).with('a_query_facet_field').and_return(facet_config)
48
+ helper.should_receive(:create_rsolr_facet_field_response_for_query_facet_field).with('a_query_facet_field', facet_config)
49
+
50
+ helper.facet_by_field_name 'a_query_facet_field'
51
+ end
52
+
53
+ describe "query facets" do
54
+ let(:facet_config) {
55
+ mock(
56
+ :query => {
57
+ 'a_simple_query' => { :fq => 'field:search', :label => 'A Human Readable label'},
58
+ 'another_query' => { :fq => 'field:different_search', :label => 'Label'},
59
+ 'without_results' => { :fq => 'field:without_results', :label => 'No results for this facet'}
60
+ }
61
+ )
62
+ }
63
+
64
+ before(:each) do
65
+ helper.should_receive(:facet_configuration_for_field).with(anything()).and_return(facet_config)
66
+
67
+ @response = mock(:facet_queries => {
68
+ 'field:search' => 10,
69
+ 'field:different_search' => 2,
70
+ 'field:not_appearing_in_the_config' => 50,
71
+ 'field:without_results' => 0
72
+ })
73
+ end
34
74
 
35
- helper.facet_by_field_name('a').should == a
75
+ it"should convert the query facets into a mock RSolr FacetField" do
76
+ field = helper.facet_by_field_name('my_query_facet_field')
77
+ field.should be_a_kind_of RSolr::Ext::Response::Facets::FacetField
78
+
79
+ field.name.should == 'my_query_facet_field'
80
+ field.items.length.should == 2
81
+ field.items.map { |x| x.value }.should_not include 'field:not_appearing_in_the_config'
82
+
83
+ facet_item = field.items.select { |x| x.value == 'a_simple_query' }.first
84
+
85
+ facet_item.value.should == 'a_simple_query'
86
+ facet_item.hits.should == 10
87
+ facet_item.label.should == 'A Human Readable label'
88
+ end
36
89
  end
37
90
  end
38
91
 
92
+
39
93
  describe "render_facet_partials" do
40
94
  it "should try to render all provided facets " do
41
95
  a = mock(:items => [1,2])
@@ -163,6 +217,18 @@ describe FacetsHelper do
163
217
  end
164
218
  end
165
219
  end
220
+
221
+ it "should replace facets for facets configured as single" do
222
+ helper.should_receive(:facet_configuration_for_field).with('single_value_facet_field').and_return(mock(:single => true))
223
+ params = { :f => { 'single_value_facet_field' => 'other_value'}}
224
+ helper.stub!(:params).and_return params
225
+
226
+ result_params = helper.add_facet_params('single_value_facet_field', 'my_value')
227
+
228
+
229
+ result_params[:f]['single_value_facet_field'].length.should == 1
230
+ result_params[:f]['single_value_facet_field'].first.should == 'my_value'
231
+ end
166
232
  end
167
233
 
168
234
  describe "add_facet_params_and_redirect" do
@@ -214,5 +280,26 @@ describe FacetsHelper do
214
280
  describe "facet_in_params?" do
215
281
 
216
282
  end
217
-
283
+
284
+ describe "#facet_display_value" do
285
+ it "should just be the facet value for an ordinary facet" do
286
+ helper.stub(:facet_configuration_for_field).with('simple_field').and_return(mock(:query => nil, :date => nil))
287
+ helper.facet_display_value('simple_field', 'asdf').should == 'asdf'
288
+ end
289
+
290
+ it "should extract the configuration label for a query facet" do
291
+ helper.stub(:facet_configuration_for_field).with('query_facet').and_return(mock(:query => { 'query_key' => { :label => 'XYZ'}}, :date => nil))
292
+ helper.facet_display_value('query_facet', 'query_key').should == 'XYZ'
293
+ end
294
+
295
+ it "should localize the label for date-type facets" do
296
+ helper.stub(:facet_configuration_for_field).with('date_facet').and_return(mock('date' => true, :query => nil))
297
+ helper.facet_display_value('date_facet', '2012-01-01').should == 'Sun, 01 Jan 2012 00:00:00 +0000'
298
+ end
299
+
300
+ it "should localize the label for date-type facets with the supplied localization options" do
301
+ helper.stub(:facet_configuration_for_field).with('date_facet').and_return(mock('date' => { :format => :short }, :query => nil))
302
+ helper.facet_display_value('date_facet', '2012-01-01').should == '01 Jan 00:00'
303
+ end
304
+ end
218
305
  end