blacklight 7.16.0 → 7.18.1

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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -0
  3. data/VERSION +1 -1
  4. data/app/components/blacklight/advanced_search_form_component.html.erb +9 -3
  5. data/app/components/blacklight/advanced_search_form_component.rb +48 -35
  6. data/app/components/blacklight/constraints_component.html.erb +19 -3
  7. data/app/components/blacklight/constraints_component.rb +5 -1
  8. data/app/components/blacklight/content_areas_shim.rb +12 -0
  9. data/app/components/blacklight/document/action_component.rb +4 -0
  10. data/app/components/blacklight/document/actions_component.html.erb +3 -5
  11. data/app/components/blacklight/document/actions_component.rb +14 -1
  12. data/app/components/blacklight/document/thumbnail_component.html.erb +3 -3
  13. data/app/components/blacklight/document/thumbnail_component.rb +11 -3
  14. data/app/components/blacklight/document_component.html.erb +4 -7
  15. data/app/components/blacklight/document_component.rb +73 -73
  16. data/app/components/blacklight/document_metadata_component.html.erb +2 -2
  17. data/app/components/blacklight/document_metadata_component.rb +13 -2
  18. data/app/components/blacklight/document_title_component.html.erb +17 -0
  19. data/app/components/blacklight/document_title_component.rb +59 -0
  20. data/app/components/blacklight/facet_field_checkboxes_component.html.erb +2 -2
  21. data/app/components/blacklight/facet_field_component.rb +4 -1
  22. data/app/components/blacklight/facet_field_list_component.html.erb +2 -2
  23. data/app/components/blacklight/facet_field_no_layout_component.rb +4 -1
  24. data/app/components/blacklight/metadata_field_component.html.erb +2 -2
  25. data/app/components/blacklight/metadata_field_layout_component.html.erb +3 -1
  26. data/app/components/blacklight/metadata_field_layout_component.rb +26 -1
  27. data/app/components/blacklight/response/view_type_button_component.html.erb +4 -0
  28. data/app/components/blacklight/response/view_type_button_component.rb +38 -0
  29. data/app/components/blacklight/response/view_type_component.html.erb +2 -5
  30. data/app/components/blacklight/response/view_type_component.rb +9 -13
  31. data/app/components/blacklight/search_bar_component.rb +4 -1
  32. data/app/components/blacklight/system/dropdown_component.html.erb +4 -7
  33. data/app/components/blacklight/system/dropdown_component.rb +24 -0
  34. data/app/components/blacklight/system/flash_message_component.html.erb +1 -1
  35. data/app/components/blacklight/system/flash_message_component.rb +7 -1
  36. data/app/components/blacklight/system/modal_component.rb +7 -1
  37. data/app/helpers/blacklight/catalog_helper_behavior.rb +2 -0
  38. data/app/views/catalog/_citation.html.erb +1 -1
  39. data/app/views/catalog/_document.html.erb +2 -2
  40. data/app/views/catalog/_facet_layout.html.erb +2 -2
  41. data/app/views/catalog/_show_main_content.html.erb +3 -3
  42. data/app/views/catalog/email.html.erb +2 -2
  43. data/app/views/catalog/email_success.html.erb +1 -1
  44. data/app/views/catalog/facet.html.erb +3 -3
  45. data/app/views/catalog/sms.html.erb +2 -2
  46. data/app/views/catalog/sms_success.html.erb +1 -1
  47. data/blacklight.gemspec +1 -1
  48. data/config/locales/blacklight.de.yml +2 -2
  49. data/lib/blacklight/configuration/view_config.rb +2 -0
  50. data/lib/blacklight/engine.rb +3 -1
  51. data/lib/blacklight/nested_open_struct_with_hash_access.rb +23 -7
  52. data/lib/blacklight/search_builder.rb +1 -0
  53. data/lib/blacklight/solr/facet_paginator.rb +2 -0
  54. data/lib/blacklight/solr/request.rb +31 -0
  55. data/lib/blacklight/solr/response.rb +2 -16
  56. data/lib/blacklight/solr/response/facets.rb +76 -22
  57. data/lib/blacklight/solr/response/params.rb +104 -0
  58. data/lib/blacklight/solr/search_builder_behavior.rb +56 -30
  59. data/lib/generators/blacklight/assets_generator.rb +6 -2
  60. data/lib/generators/blacklight/install_generator.rb +5 -5
  61. data/lib/generators/blacklight/solr_generator.rb +4 -2
  62. data/lib/generators/blacklight/user_generator.rb +5 -3
  63. data/spec/components/blacklight/document_component_spec.rb +3 -3
  64. data/spec/helpers/blacklight/configuration_helper_behavior_spec.rb +6 -7
  65. data/spec/helpers/blacklight_helper_spec.rb +2 -2
  66. data/spec/helpers/catalog_helper_spec.rb +1 -1
  67. data/spec/lib/blacklight/nested_open_struct_with_hash_access_spec.rb +14 -0
  68. data/spec/models/blacklight/solr/facet_paginator_spec.rb +4 -0
  69. data/spec/models/blacklight/solr/request_spec.rb +62 -29
  70. data/spec/models/blacklight/solr/response/facets_spec.rb +109 -0
  71. data/spec/models/blacklight/solr/response_spec.rb +10 -0
  72. data/spec/models/blacklight/solr/search_builder_spec.rb +26 -0
  73. data/spec/services/blacklight/search_service_spec.rb +1 -1
  74. data/spec/views/catalog/_constraints.html.erb_spec.rb +1 -1
  75. data/spec/views/catalog/_view_type_group.html.erb_spec.rb +8 -9
  76. metadata +14 -8
@@ -323,7 +323,7 @@ RSpec.describe CatalogHelper do
323
323
 
324
324
  it "supports view-specific field configuration" do
325
325
  allow(helper).to receive(:document_index_view_type).and_return(:some_view_type)
326
- blacklight_config.view.some_view_type.display_type_field = :other_type
326
+ blacklight_config.view.some_view_type(display_type_field: :other_type)
327
327
  doc = { other_type: "document" }
328
328
  expect(helper.render_document_class(doc)).to eq "blacklight-document"
329
329
  end
@@ -23,4 +23,18 @@ RSpec.describe Blacklight::NestedOpenStructWithHashAccess do
23
23
  expect(subject.blah).to have_attributes(key: :blah)
24
24
  end
25
25
  end
26
+
27
+ describe 'adding new parameters' do
28
+ subject { described_class.new(Blacklight::Configuration::Field) }
29
+
30
+ it 'strips the trailing !' do
31
+ subject.blaH!
32
+ expect(subject.blah).to have_attributes(key: :blah)
33
+ end
34
+
35
+ it 'supports direct assignment' do
36
+ subject.blah = '123'
37
+ expect(subject.blah).to eq '123'
38
+ end
39
+ end
26
40
  end
@@ -20,5 +20,9 @@ RSpec.describe Blacklight::Solr::FacetPaginator, api: true do
20
20
  it 'defaults to "index" if no limit is given' do
21
21
  expect(described_class.new([]).sort).to eq 'index'
22
22
  end
23
+
24
+ it 'handles json facet api-style parameter sorts' do
25
+ expect(described_class.new([], sort: { count: :desc }).sort).to eq 'count'
26
+ end
23
27
  end
24
28
  end
@@ -1,36 +1,69 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  RSpec.describe Blacklight::Solr::Request, api: true do
4
- before do
5
- subject[:qt] = 'hey'
6
- subject[:fq] = ["what's up.", "dood"]
7
- subject['q'] = "what's"
8
- subject[:wt] = "going"
9
- subject[:start] = "on"
10
- subject[:rows] = "Man"
11
- subject['hl'] = "I"
12
- subject['hl.fl'] = "wish"
13
- subject['group'] = "I"
14
- subject['defType'] = "had"
15
- subject['spellcheck'] = "a"
16
- subject['spellcheck.q'] = "fleece"
17
- subject['f.title_facet.facet.limit'] = "vest"
18
- subject['facet.field'] = []
4
+ context 'with some solr parameter keys' do
5
+ before do
6
+ subject[:qt] = 'hey'
7
+ subject[:fq] = ["what's up.", "dood"]
8
+ subject['q'] = "what's"
9
+ subject[:wt] = "going"
10
+ subject[:start] = "on"
11
+ subject[:rows] = "Man"
12
+ subject['hl'] = "I"
13
+ subject['hl.fl'] = "wish"
14
+ subject['group'] = "I"
15
+ subject['defType'] = "had"
16
+ subject['spellcheck'] = "a"
17
+ subject['spellcheck.q'] = "fleece"
18
+ subject['f.title_facet.facet.limit'] = "vest"
19
+ subject['facet.field'] = []
20
+ end
21
+
22
+ it "accepts valid parameters" do
23
+ expect(subject.to_hash).to eq("defType" => "had",
24
+ "f.title_facet.facet.limit" => "vest",
25
+ "fq" => ["what's up.", "dood"],
26
+ "group" => "I",
27
+ "hl" => "I",
28
+ "hl.fl" => "wish",
29
+ "q" => "what's",
30
+ "qt" => "hey",
31
+ "rows" => "Man",
32
+ "spellcheck" => "a",
33
+ "spellcheck.q" => "fleece",
34
+ "start" => "on",
35
+ "wt" => "going")
36
+ end
37
+ end
38
+
39
+ describe '#append_query' do
40
+ it 'populates the q parameter' do
41
+ subject.append_query 'this is my query'
42
+ expect(subject['q']).to eq 'this is my query'
43
+ end
44
+
45
+ it 'handles multiple queries by converting it to a boolean query' do
46
+ subject.append_query 'this is my query'
47
+ subject.append_query 'another:query'
48
+ expect(subject).not_to have_key 'q'
49
+ expect(subject.dig('json', 'query', 'bool', 'must')).to match_array ['this is my query', 'another:query']
50
+ end
19
51
  end
20
52
 
21
- it "accepts valid parameters" do
22
- expect(subject.to_hash).to eq("defType" => "had",
23
- "f.title_facet.facet.limit" => "vest",
24
- "fq" => ["what's up.", "dood"],
25
- "group" => "I",
26
- "hl" => "I",
27
- "hl.fl" => "wish",
28
- "q" => "what's",
29
- "qt" => "hey",
30
- "rows" => "Man",
31
- "spellcheck" => "a",
32
- "spellcheck.q" => "fleece",
33
- "start" => "on",
34
- "wt" => "going")
53
+ describe '#append_boolean_query' do
54
+ it 'populates the boolean query with the queries' do
55
+ subject.append_boolean_query :must, 'required'
56
+ subject.append_boolean_query :should, 'optional'
57
+ subject.append_boolean_query :should, 'also optional'
58
+
59
+ expect(subject.dig('json', 'query', 'bool')).to include should: ['optional', 'also optional'], must: ['required']
60
+ end
61
+
62
+ it 'converts existing q parameters to a boolean query' do
63
+ subject['q'] = 'some query'
64
+ subject.append_boolean_query :must, 'also required'
65
+
66
+ expect(subject.dig('json', 'query', 'bool', 'must')).to match_array ['some query', 'also required']
67
+ end
35
68
  end
36
69
  end
@@ -160,6 +160,12 @@ RSpec.describe Blacklight::Solr::Response::Facets, api: true do
160
160
  expect(missing.label).to eq "[Missing]"
161
161
  expect(missing.fq).to eq "-some_field:[* TO *]"
162
162
  end
163
+
164
+ it 'extracts the missing field data to a separate facet field attribute' do
165
+ missing = subject.aggregations["some_field"].missing
166
+
167
+ expect(missing).to have_attributes(label: '[Missing]', hits: 2)
168
+ end
163
169
  end
164
170
 
165
171
  describe "query facets" do
@@ -278,4 +284,107 @@ RSpec.describe Blacklight::Solr::Response::Facets, api: true do
278
284
  expect(field.items.first.items.first.fq).to eq('field_a' => 'a')
279
285
  end
280
286
  end
287
+
288
+ describe 'json facets' do
289
+ subject { Blacklight::Solr::Response.new(response, {}, blacklight_config: blacklight_config) }
290
+
291
+ let(:response) do
292
+ {
293
+ facets: {
294
+ "count": 32,
295
+ "categories": {
296
+ "buckets": [
297
+ {
298
+ "val": "electronics",
299
+ "count": 12,
300
+ "max_price": 60
301
+ },
302
+ {
303
+ "val": "currency",
304
+ "count": 4
305
+ },
306
+ {
307
+ "val": "memory",
308
+ "count": 3
309
+ }
310
+ ]
311
+ }
312
+ }
313
+ }
314
+ end
315
+ let(:facet_config) do
316
+ Blacklight::Configuration::FacetField.new(key: 'categories', json: true, query: false)
317
+ end
318
+
319
+ let(:blacklight_config) { double(facet_fields: { 'categories' => facet_config }) }
320
+ let(:field) { subject.aggregations['categories'] }
321
+
322
+ it 'has access to the original response data' do
323
+ expect(field.data).to include 'buckets'
324
+ end
325
+
326
+ it 'converts buckets into facet items' do
327
+ expect(field.items.length).to eq 3
328
+ end
329
+
330
+ context 'with nested buckets' do
331
+ let(:response) do
332
+ {
333
+ facets: {
334
+ "categories": {
335
+ "buckets": [
336
+ {
337
+ "val": "electronics",
338
+ "count": 12,
339
+ "top_manufacturer": {
340
+ "buckets": [{
341
+ "val": "corsair",
342
+ "count": 3
343
+ }]
344
+ }
345
+ },
346
+ {
347
+ "val": "currency",
348
+ "count": 4,
349
+ "top_manufacturer": {
350
+ "buckets": [{
351
+ "val": "boa",
352
+ "count": 1
353
+ }]
354
+ }
355
+ }
356
+ ]
357
+ }
358
+ }
359
+ }
360
+ end
361
+
362
+ it 'converts nested buckets into pivot facets' do
363
+ expect(field.items.first).to have_attributes hits: 12
364
+ expect(field.items.first.items.first).to have_attributes field: 'top_manufacturer', value: 'corsair', hits: 3, fq: { "categories" => "electronics" }
365
+ end
366
+ end
367
+
368
+ context 'with missing values' do
369
+ let(:response) do
370
+ {
371
+ facets: {
372
+ "categories": {
373
+ "missing" => { "count" => 13 },
374
+ "buckets" => [{ "val" => "India", "count" => 2 }, { "val" => "Iran", "count" => 2 }]
375
+ }
376
+ }
377
+ }
378
+ end
379
+
380
+ it 'converts "missing" facet data into a missing facet item' do
381
+ expect(field.items.length).to eq 2
382
+ expect(field.missing).to have_attributes(hits: 13)
383
+ end
384
+ end
385
+
386
+ it 'exposes any extra query function results' do
387
+ expect(field.items.first.data).to include 'max_price' => 60
388
+ end
389
+ end
281
390
  end
@@ -120,6 +120,16 @@ RSpec.describe Blacklight::Solr::Response, api: true do
120
120
  expect(r.params['test']).to eq :test
121
121
  end
122
122
 
123
+ it 'extracts json params' do
124
+ raw_response = eval(mock_query_response)
125
+ raw_response['responseHeader']['params']['test'] = 'from query'
126
+ raw_response['responseHeader']['params'].delete('rows')
127
+ raw_response['responseHeader']['params']['json'] = { limit: 5, params: { test: 'from json params' } }.to_json
128
+ r = described_class.new(raw_response, raw_response['params'])
129
+ expect(r.params['test']).to eq 'from query'
130
+ expect(r.rows).to eq 5
131
+ end
132
+
123
133
  it 'provides the solr-returned params and "rows" should be 11' do
124
134
  raw_response = eval(mock_query_response)
125
135
  r = described_class.new(raw_response, {})
@@ -259,6 +259,23 @@ RSpec.describe Blacklight::Solr::SearchBuilderBehavior, api: true do
259
259
  end
260
260
  end
261
261
 
262
+ describe 'with a json facet' do
263
+ let(:user_params) { { f: { json_facet: ['value'] } }.with_indifferent_access }
264
+
265
+ before do
266
+ blacklight_config.add_facet_field 'json_facet', field: 'foo', json: { bar: 'baz' }
267
+ end
268
+
269
+ it "has proper solr parameters" do
270
+ expect(subject[:fq]).to include('{!term f=foo}value')
271
+ expect(subject.dig(:json, :facet, 'json_facet')).to include(
272
+ field: 'foo',
273
+ type: 'terms',
274
+ bar: 'baz'
275
+ )
276
+ end
277
+ end
278
+
262
279
  describe 'with multi-valued facets' do
263
280
  let(:user_params) { { f_inclusive: { format: %w[Book Movie CD] } } }
264
281
 
@@ -783,4 +800,13 @@ RSpec.describe Blacklight::Solr::SearchBuilderBehavior, api: true do
783
800
  expect(subject.to_hash.with_indifferent_access.dig(:json, :query, :bool, :must, 1, :edismax, :qf)).to eq '${author_qf}'
784
801
  end
785
802
  end
803
+
804
+ describe '#where' do
805
+ let(:user_params) { {} }
806
+
807
+ it 'adds additional query filters on the search' do
808
+ subject.where(id: [1, 2, 3])
809
+ expect(subject.to_hash).to include q: '{!lucene}id:(1 OR 2 OR 3)'
810
+ end
811
+ end
786
812
  end
@@ -477,7 +477,7 @@ RSpec.describe Blacklight::SearchService, api: true do
477
477
  end
478
478
 
479
479
  before do
480
- blacklight_config.view.opensearch.title_field = :field
480
+ blacklight_config.view.opensearch(title_field: :field)
481
481
  allow(repository).to receive(:search).and_return(mock_response)
482
482
  end
483
483
 
@@ -3,7 +3,7 @@
3
3
  RSpec.describe "catalog/constraints" do
4
4
  let :blacklight_config do
5
5
  Blacklight::Configuration.new do |config|
6
- config.view.xyz
6
+ config.view.xyz({})
7
7
  end
8
8
  end
9
9
 
@@ -3,13 +3,9 @@
3
3
  RSpec.describe "catalog/_view_type_group" do
4
4
  let(:blacklight_config) { Blacklight::Configuration.new }
5
5
  let(:response) { instance_double(Blacklight::Solr::Response, empty?: false) }
6
- let(:icon_instance) { instance_double(Blacklight::Icon) }
7
6
 
8
7
  before do
9
8
  allow(view).to receive(:view_label), &:to_s
10
- allow(Blacklight::Icon).to receive(:new).and_return icon_instance
11
- allow(icon_instance).to receive(:svg).and_return '<svg></svg>'
12
- allow(icon_instance).to receive(:options).and_return({})
13
9
  allow(view).to receive_messages(how_sort_and_per_page?: true, blacklight_config: blacklight_config)
14
10
  controller.request.path_parameters[:action] = 'index'
15
11
  assign(:response, response)
@@ -24,13 +20,16 @@ RSpec.describe "catalog/_view_type_group" do
24
20
  it "displays the group" do
25
21
  blacklight_config.configure do |config|
26
22
  config.view.delete(:list)
27
- config.view.a
28
- config.view.b
29
- config.view.c
23
+ config.view.a(icon: :list)
24
+ config.view.b(icon: :list)
25
+ config.view.c(icon: :list)
30
26
  end
31
27
  render partial: 'catalog/view_type_group'
32
28
  expect(rendered).to have_selector('.btn-group.view-type-group')
33
29
  expect(rendered).to have_selector('.view-type-a', text: 'a')
30
+ within '.view-type-a' do
31
+ expect(rendered).to have_selector 'svg'
32
+ end
34
33
  expect(rendered).to have_selector('.view-type-b', text: 'b')
35
34
  expect(rendered).to have_selector('.view-type-c', text: 'c')
36
35
  end
@@ -38,8 +37,8 @@ RSpec.describe "catalog/_view_type_group" do
38
37
  it "sets the current view to 'active'" do
39
38
  blacklight_config.configure do |config|
40
39
  config.view.delete(:list)
41
- config.view.a
42
- config.view.b
40
+ config.view.a(icon: :list)
41
+ config.view.b(icon: :list)
43
42
  end
44
43
  render partial: 'catalog/view_type_group'
45
44
  expect(rendered).to have_selector('.active', text: 'a')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blacklight
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.16.0
4
+ version: 7.18.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Rochkind
@@ -14,10 +14,10 @@ authors:
14
14
  - Dan Funk
15
15
  - Naomi Dushay
16
16
  - Justin Coyne
17
- autorequire:
17
+ autorequire:
18
18
  bindir: exe
19
19
  cert_chain: []
20
- date: 2021-03-30 00:00:00.000000000 Z
20
+ date: 2021-04-26 00:00:00.000000000 Z
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
23
23
  name: rails
@@ -129,14 +129,14 @@ dependencies:
129
129
  requirements:
130
130
  - - ">="
131
131
  - !ruby/object:Gem::Version
132
- version: 2.23.0
132
+ version: 2.28.0
133
133
  type: :runtime
134
134
  prerelease: false
135
135
  version_requirements: !ruby/object:Gem::Requirement
136
136
  requirements:
137
137
  - - ">="
138
138
  - !ruby/object:Gem::Version
139
- version: 2.23.0
139
+ version: 2.28.0
140
140
  - !ruby/object:Gem::Dependency
141
141
  name: rsolr
142
142
  requirement: !ruby/object:Gem::Requirement
@@ -402,6 +402,7 @@ files:
402
402
  - app/components/blacklight/constraint_layout_component.rb
403
403
  - app/components/blacklight/constraints_component.html.erb
404
404
  - app/components/blacklight/constraints_component.rb
405
+ - app/components/blacklight/content_areas_shim.rb
405
406
  - app/components/blacklight/document/action_component.html.erb
406
407
  - app/components/blacklight/document/action_component.rb
407
408
  - app/components/blacklight/document/actions_component.html.erb
@@ -420,6 +421,8 @@ files:
420
421
  - app/components/blacklight/document_component.rb
421
422
  - app/components/blacklight/document_metadata_component.html.erb
422
423
  - app/components/blacklight/document_metadata_component.rb
424
+ - app/components/blacklight/document_title_component.html.erb
425
+ - app/components/blacklight/document_title_component.rb
423
426
  - app/components/blacklight/facet_field_checkboxes_component.html.erb
424
427
  - app/components/blacklight/facet_field_checkboxes_component.rb
425
428
  - app/components/blacklight/facet_field_component.html.erb
@@ -448,6 +451,8 @@ files:
448
451
  - app/components/blacklight/response/sort_component.rb
449
452
  - app/components/blacklight/response/spellcheck_component.html.erb
450
453
  - app/components/blacklight/response/spellcheck_component.rb
454
+ - app/components/blacklight/response/view_type_button_component.html.erb
455
+ - app/components/blacklight/response/view_type_button_component.rb
451
456
  - app/components/blacklight/response/view_type_component.html.erb
452
457
  - app/components/blacklight/response/view_type_component.rb
453
458
  - app/components/blacklight/search_bar_component.html.erb
@@ -691,6 +696,7 @@ files:
691
696
  - lib/blacklight/solr/response/group_response.rb
692
697
  - lib/blacklight/solr/response/more_like_this.rb
693
698
  - lib/blacklight/solr/response/pagination_methods.rb
699
+ - lib/blacklight/solr/response/params.rb
694
700
  - lib/blacklight/solr/response/response.rb
695
701
  - lib/blacklight/solr/response/spelling.rb
696
702
  - lib/blacklight/solr/search_builder_behavior.rb
@@ -881,7 +887,7 @@ homepage: http://projectblacklight.org/
881
887
  licenses:
882
888
  - Apache 2.0
883
889
  metadata: {}
884
- post_install_message:
890
+ post_install_message:
885
891
  rdoc_options: []
886
892
  require_paths:
887
893
  - lib
@@ -896,8 +902,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
896
902
  - !ruby/object:Gem::Version
897
903
  version: '0'
898
904
  requirements: []
899
- rubygems_version: 3.1.4
900
- signing_key:
905
+ rubygems_version: 3.2.3
906
+ signing_key:
901
907
  specification_version: 4
902
908
  summary: Blacklight provides a discovery interface for any Solr (http://lucene.apache.org/solr)
903
909
  index.