blacklight 7.8.1 → 7.9.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. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/app/assets/stylesheets/blacklight/_facets.scss +20 -4
  4. data/app/components/blacklight/facet_item_pivot_component.rb +84 -0
  5. data/app/helpers/blacklight/facets_helper_behavior.rb +12 -5
  6. data/app/helpers/blacklight/render_constraints_helper_behavior.rb +2 -2
  7. data/app/models/blacklight/icon.rb +5 -9
  8. data/app/models/concerns/blacklight/document.rb +0 -10
  9. data/app/presenters/blacklight/facet_item_presenter.rb +1 -1
  10. data/app/views/catalog/_constraints.html.erb +1 -1
  11. data/app/views/catalog/_facet_pivot.html.erb +3 -18
  12. data/config/locales/blacklight.ar.yml +3 -0
  13. data/config/locales/blacklight.de.yml +3 -0
  14. data/config/locales/blacklight.en.yml +3 -0
  15. data/config/locales/blacklight.es.yml +3 -0
  16. data/config/locales/blacklight.fr.yml +3 -0
  17. data/config/locales/blacklight.hu.yml +3 -0
  18. data/config/locales/blacklight.it.yml +3 -0
  19. data/config/locales/blacklight.nl.yml +3 -0
  20. data/config/locales/blacklight.pt-BR.yml +3 -0
  21. data/config/locales/blacklight.sq.yml +3 -0
  22. data/config/locales/blacklight.zh.yml +3 -0
  23. data/lib/blacklight/configuration.rb +35 -8
  24. data/lib/generators/blacklight/templates/catalog_controller.rb +1 -1
  25. data/package-lock.json +4 -4
  26. data/package.json +1 -1
  27. data/spec/components/blacklight/facet_item_pivot_component_spec.rb +66 -0
  28. data/spec/features/facets_spec.rb +20 -0
  29. data/spec/models/blacklight/configuration_spec.rb +4 -0
  30. data/spec/models/blacklight/icon_spec.rb +5 -13
  31. data/spec/spec_helper.rb +1 -0
  32. metadata +5 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 797fccb08c32206cbf11ab04efa5b980456a8a1ff2f949940ce68b9b29843720
4
- data.tar.gz: 26608839399a44a7f33f4313337a35c5a064578daa0819cc845a601c9d058d3c
3
+ metadata.gz: bd2196992d71cdb76b3080eb944caa30d0534fd0b8954f641e50ba6287e00c75
4
+ data.tar.gz: 3d273772786614bae0a216a1be97b038d90f24c1ddea1aee25a3a993613bed97
5
5
  SHA512:
6
- metadata.gz: 2066cfd8c17650d43b39707f8d73c39745307eff3795875833f0a1e0c794ba92a8aae1aa061db59e5a39154332e0e5addcb3a4d4463894ccc641eee57ed40b7e
7
- data.tar.gz: 3403d40968957aadb62eba71caed870704c23bbebf93f98910bba9931ca136b80d79ba411cb1852a2a48bf227e3456fd1d91fc8ecd01b7b8aad852dbb3f4ab8e
6
+ metadata.gz: 57ea5cb5460c6eff4a4554f73c8da22552984a9860ccb116f251d8f799d057b9b864e15b722319548c390df4fa686a9f46a96be5972b56eef46d9271e3e37368
7
+ data.tar.gz: b364146ff5cec3708b246b917bf09cd11000e92e6e6d7103b363479c342091d1da759bc952718788476b83abd4b32c95365a52206337118ac8782f257e59376f
data/VERSION CHANGED
@@ -1 +1 @@
1
- 7.8.1
1
+ 7.9.0
@@ -150,10 +150,26 @@
150
150
 
151
151
  .pivot-facet {
152
152
  @extend .list-unstyled;
153
+ @extend .py-1;
154
+ @extend .px-4;
155
+ }
156
+
157
+ .facet-leaf-node {
158
+ margin-left: 1rem;
159
+ padding-right: 1rem;
160
+ margin-top: -1.5rem;
161
+ }
153
162
 
154
- ul, .pivot-facet {
155
- @extend .list-unstyled;
156
- @extend .py-1;
157
- @extend .px-3;
163
+ .facet-toggle-handle {
164
+ margin: 0;
165
+ margin-left: -5px;
166
+ padding: 0;
167
+
168
+ &.collapsed {
169
+ .show { display: block; }
170
+ .hide { display: none; }
158
171
  }
172
+
173
+ .show { display: none; }
174
+ .hide { display: block; }
159
175
  }
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ # Render facet items and any subtree
5
+ class FacetItemPivotComponent < ::ViewComponent::Base
6
+ # Somewhat arbitrary number; the only important thing is that
7
+ # it is bigger than the number of leaf nodes in any collapsing
8
+ # pivot facet on the page.
9
+ ID_COUNTER_MAX = 2**20 - 1
10
+
11
+ # Mint a (sufficiently) unique identifier, so we can associate
12
+ # the expand/collapse control with labels
13
+ def self.mint_id
14
+ @id_counter = ((@id_counter || 0) + 1) % ID_COUNTER_MAX
15
+
16
+ # We convert the ID to hex for markup compactness
17
+ @id_counter.to_s(16)
18
+ end
19
+
20
+ with_collection_parameter :facet_item
21
+
22
+ def initialize(facet_item:, wrapping_element: 'li', suppress_link: false, collapsing: nil)
23
+ @facet_item = facet_item
24
+ @wrapping_element = wrapping_element
25
+ @suppress_link = suppress_link
26
+ @collapsing = collapsing.nil? ? facet_item.facet_config.collapsing : collapsing
27
+ @icons = { show: '⊞', hide: '⊟' }.merge(facet_item.facet_config.icons || {})
28
+ end
29
+
30
+ def call
31
+ facet = Blacklight::FacetItemComponent.new(facet_item: @facet_item, wrapping_element: nil, suppress_link: @suppress_link)
32
+
33
+ id = "h-#{self.class.mint_id}" if @collapsing && has_items?
34
+
35
+ content_tag @wrapping_element, role: 'treeitem' do
36
+ concat facet_toggle_button(id) if has_items? && @collapsing
37
+ concat content_tag('span', render_component(facet), class: "facet-values #{'facet-leaf-node' if has_items? && @collapsing}", id: id && "#{id}_label")
38
+
39
+ if has_items?
40
+ concat(content_tag('ul', class: "pivot-facet list-unstyled #{'collapse' if @collapsing}", id: id, role: 'group') do
41
+ render_component(
42
+ self.class.with_collection(
43
+ @facet_item.items.map { |i| facet_item_presenter(i) }
44
+ )
45
+ )
46
+ end)
47
+ end
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def has_items?
54
+ @facet_item.items.present?
55
+ end
56
+
57
+ def facet_toggle_button(id)
58
+ content_tag 'button', class: 'btn facet-toggle-handle collapsed',
59
+ data: { toggle: 'collapse', target: "##{id}" },
60
+ aria: { expanded: false, controls: id, describedby: "#{id}_label" } do
61
+ concat toggle_icon(:show)
62
+ concat toggle_icon(:hide)
63
+ end
64
+ end
65
+
66
+ def toggle_icon(type)
67
+ content_tag 'span', class: type do
68
+ concat @icons[type]
69
+ concat content_tag('span', t(type, scope: 'blacklight.search.facets.pivot'), class: 'sr-only')
70
+ end
71
+ end
72
+
73
+ # This is a little convoluted in Blacklight 7 in order to maintain backwards-compat
74
+ # with overrides of deprecated helpers. In 8.x, we can just call Component#render_in
75
+ # and call it a day
76
+ def render_component(component)
77
+ @view_context.render(component)
78
+ end
79
+
80
+ def facet_item_presenter(facet_item)
81
+ Blacklight::FacetItemPresenter.new(facet_item, @facet_item.facet_config, @view_context, @facet_item.facet_field, @facet_item.search_state)
82
+ end
83
+ end
84
+ end
@@ -81,7 +81,11 @@ module Blacklight::FacetsHelperBehavior
81
81
  return unless should_render_facet?(display_facet, field_config)
82
82
  end
83
83
  options = options.dup
84
- options[:partial] ||= facet_partial_name(display_facet)
84
+
85
+ Deprecation.silence(Blacklight::FacetsHelperBehavior) do
86
+ options[:partial] ||= facet_partial_name(display_facet)
87
+ end
88
+
85
89
  options[:layout] ||= "facet_layout" unless options.key?(:layout)
86
90
  options[:locals] ||= {}
87
91
  options[:locals][:field_name] ||= display_facet.name
@@ -97,13 +101,12 @@ module Blacklight::FacetsHelperBehavior
97
101
  # to filter undesireable facet items so they don't appear in the UI
98
102
  def render_facet_limit_list(paginator, facet_field, wrapping_element = :li)
99
103
  facet_config ||= facet_configuration_for_field(facet_field)
100
- component = facet_config.fetch(:item_component, Blacklight::FacetItemComponent)
101
104
 
102
105
  collection = paginator.items.map do |item|
103
106
  facet_item_presenter(facet_config, item, facet_field)
104
107
  end
105
108
 
106
- render(component.with_collection(collection, wrapping_element: wrapping_element))
109
+ render(facet_item_component_class(facet_config).with_collection(collection, wrapping_element: wrapping_element))
107
110
  end
108
111
  deprecation_deprecate :render_facet_limit_list
109
112
 
@@ -288,8 +291,12 @@ module Blacklight::FacetsHelperBehavior
288
291
  end
289
292
 
290
293
  def facet_item_component(facet_config, facet_item, facet_field, **args)
291
- component = facet_config.fetch(:item_component, Blacklight::FacetItemComponent)
292
- component.new(facet_item: facet_item_presenter(facet_config, facet_item, facet_field), **args).with_view_context(self)
294
+ facet_item_component_class(facet_config).new(facet_item: facet_item_presenter(facet_config, facet_item, facet_field), **args).with_view_context(self)
295
+ end
296
+
297
+ def facet_item_component_class(facet_config)
298
+ default_component = facet_config.pivot ? Blacklight::FacetItemPivotComponent : Blacklight::FacetItemComponent
299
+ facet_config.fetch(:item_component, default_component)
293
300
  end
294
301
 
295
302
  # We can't use .deprecation_deprecate here, because the new components need to
@@ -18,7 +18,7 @@ module Blacklight::RenderConstraintsHelperBehavior
18
18
  search_state = convert_to_search_state(params_or_search_state)
19
19
  search_state.has_constraints?
20
20
  end
21
- deprecation_deprecate :query_has_constraints?
21
+ deprecation_deprecate query_has_constraints?: 'use search_state#has_constraints?'
22
22
 
23
23
  ##
24
24
  # Render the actual constraints, not including header or footer
@@ -50,7 +50,7 @@ module Blacklight::RenderConstraintsHelperBehavior
50
50
  return "".html_safe if search_state.query_param.blank?
51
51
 
52
52
  Deprecation.silence(Blacklight::RenderConstraintsHelperBehavior) do
53
- render_constraint_element(constraint_query_label(search_state),
53
+ render_constraint_element(constraint_query_label(search_state.params),
54
54
  search_state.query_param,
55
55
  classes: ["query"],
56
56
  remove: remove_constraint_url(search_state))
@@ -26,17 +26,12 @@ module Blacklight
26
26
  def svg
27
27
  svg = ng_xml.at_xpath('svg')
28
28
  svg['role'] = role
29
- svg['aria-labelledby'] = unique_id if label
30
- svg.add_child("<title id='#{unique_id}'>#{icon_label}</title>") if label
29
+ svg.prepend_child("<title>#{icon_label}</title>") if label
31
30
  ng_xml.to_xml
32
31
  end
33
32
 
34
33
  def icon_label
35
- I18n.translate("blacklight.icon.#{icon_name_context}", default: "#{icon_name} icon")
36
- end
37
-
38
- def unique_id
39
- @unique_id ||= "bl-icon-#{icon_name_context}-#{SecureRandom.hex(8)}"
34
+ I18n.translate("blacklight.icon.#{icon_name_context}", default: icon_name.to_s.titleize)
40
35
  end
41
36
 
42
37
  ##
@@ -44,7 +39,8 @@ module Blacklight
44
39
  def options
45
40
  {
46
41
  class: classes,
47
- "aria-hidden": (true if aria_hidden)
42
+ "aria-hidden": (true if aria_hidden),
43
+ "aria-label": (icon_label if label)
48
44
  }
49
45
  end
50
46
 
@@ -79,7 +75,7 @@ module Blacklight
79
75
  end
80
76
 
81
77
  def classes
82
- " blacklight-icons #{@classes} ".strip
78
+ " blacklight-icons blacklight-icon-#{icon_name} #{@classes} ".strip
83
79
  end
84
80
  end
85
81
  end
@@ -16,16 +16,6 @@ require 'globalid'
16
16
  # transformation formats.
17
17
  #
18
18
  module Blacklight::Document
19
- autoload :ActiveModelShim, 'blacklight/document/active_model_shim'
20
- autoload :SchemaOrg, 'blacklight/document/schema_org'
21
- autoload :CacheKey, 'blacklight/document/cache_key'
22
- autoload :DublinCore, 'blacklight/document/dublin_core'
23
- autoload :Email, 'blacklight/document/email'
24
- autoload :SemanticFields, 'blacklight/document/semantic_fields'
25
- autoload :Sms, 'blacklight/document/sms'
26
- autoload :Extensions, 'blacklight/document/extensions'
27
- autoload :Export, 'blacklight/document/export'
28
-
29
19
  extend ActiveSupport::Concern
30
20
  include Blacklight::Document::SchemaOrg
31
21
  include Blacklight::Document::SemanticFields
@@ -4,7 +4,7 @@ module Blacklight
4
4
  class FacetItemPresenter
5
5
  attr_reader :facet_item, :facet_config, :view_context, :search_state, :facet_field
6
6
 
7
- delegate :hits, to: :facet_item
7
+ delegate :hits, :items, to: :facet_item
8
8
 
9
9
  def initialize(facet_item, facet_config, view_context, facet_field, search_state = view_context.search_state)
10
10
  @facet_item = facet_item
@@ -1,4 +1,4 @@
1
- <% if query_has_constraints? %>
1
+ <% if Deprecation.silence(Blacklight::RenderConstraintsHelperBehavior) { query_has_constraints? } %>
2
2
  <div id="appliedParams" class="clearfix constraints-container">
3
3
  <h2 class="sr-only"><%= t('blacklight.search.search_constraints_header') %></h2>
4
4
 
@@ -1,18 +1,3 @@
1
- <ul class="pivot-facet list-unstyled">
2
- <% display_facet.items.each do |item| -%>
3
- <li>
4
- <span class="facet-values">
5
- <% if facet_in_params?(field_name, item) %>
6
- <%= render_selected_facet_value(field_name, item) %>
7
- <% else %>
8
- <%= render_facet_value(field_name, item) %>
9
- <% end -%>
10
- </span>
11
-
12
- <% unless item.items.blank? %>
13
- <%= render 'facet_pivot', display_facet: item, field_name: field_name %>
14
- <% end %>
15
- </li>
16
- <% end %>
17
-
18
- </ul>
1
+ <%= render(Blacklight::FacetFieldListComponent.new(
2
+ facet_field: facet_field_presenter(facet_field.merge(item_component: Blacklight::FacetItemPivotComponent), display_facet),
3
+ layout: false)) %>
@@ -214,6 +214,9 @@ ar:
214
214
  remove: '[إزالة]'
215
215
  missing: "[غير موجود]"
216
216
  all: الكل
217
+ pivot:
218
+ show: فتح
219
+ hide: "إغلاق"
217
220
  group:
218
221
  more: 'المزيد »'
219
222
  filters:
@@ -194,6 +194,9 @@ de:
194
194
  selected:
195
195
  remove: '[entfernen]'
196
196
  missing: [fehlt]
197
+ pivot:
198
+ show: Öffnen
199
+ hide: Schließen
197
200
  group:
198
201
  more: 'mehr »'
199
202
  filters:
@@ -194,6 +194,9 @@ en:
194
194
  remove: '[remove]'
195
195
  missing: "[Missing]"
196
196
  all: All
197
+ pivot:
198
+ show: Show
199
+ hide: Hide
197
200
  group:
198
201
  more: 'more »'
199
202
  filters:
@@ -194,6 +194,9 @@ es:
194
194
  selected:
195
195
  remove: '[borrar]'
196
196
  missing: '[Falta]'
197
+ pivot:
198
+ show: Abierto
199
+ hide: Cerrar
197
200
  group:
198
201
  more: 'más »'
199
202
  filters:
@@ -197,6 +197,9 @@ fr:
197
197
  selected:
198
198
  remove: '[ X ]'
199
199
  missing: '[manquante]'
200
+ pivot:
201
+ show: Ouvrir
202
+ hide: Fermer
200
203
  group:
201
204
  more: 'plus »'
202
205
  filters:
@@ -194,6 +194,9 @@ hu:
194
194
  selected:
195
195
  remove: '[eltávolítás]'
196
196
  missing: "[Hiányzó]"
197
+ pivot:
198
+ show: Megnyitás
199
+ hide: Bezárás
197
200
  group:
198
201
  more: 'több »'
199
202
  filters:
@@ -194,6 +194,9 @@ it:
194
194
  selected:
195
195
  remove: '[cancella]'
196
196
  missing: [Mancante]
197
+ pivot:
198
+ show: Apri
199
+ hide: Chiudi
197
200
  group:
198
201
  more: 'altri »'
199
202
  filters:
@@ -194,6 +194,9 @@ nl:
194
194
  selected:
195
195
  remove: '[verwijder]'
196
196
  missing: "[Ontbrekend]"
197
+ pivot:
198
+ show: Openen
199
+ hide: Sluiten
197
200
  group:
198
201
  more: 'meer »'
199
202
  filters:
@@ -195,6 +195,9 @@ pt-BR:
195
195
  selected:
196
196
  remove: '[remover]'
197
197
  missing: [Ausência]
198
+ pivot:
199
+ show: Abrir
200
+ hide: Fechar
198
201
  group:
199
202
  more: 'mais »'
200
203
  filters:
@@ -194,6 +194,9 @@ sq:
194
194
  selected:
195
195
  remove: '[fshije]'
196
196
  missing: "[Mungon]"
197
+ pivot:
198
+ show: Hape
199
+ hide: "Mbylle"
197
200
  group:
198
201
  more: 'më shumë »'
199
202
  filters:
@@ -194,6 +194,9 @@ zh:
194
194
  selected:
195
195
  remove: '[删除]'
196
196
  missing: "[未找到]"
197
+ pivot:
198
+ show: 打开
199
+ hide: 关
197
200
  group:
198
201
  more: '更多 »'
199
202
  filters:
@@ -282,15 +282,10 @@ module Blacklight
282
282
  # Provide a 'deep copy' of Blacklight::Configuration that can be modified without effecting
283
283
  # the original Blacklight::Configuration instance.
284
284
  #
285
- # Rails 4.x provides `#deep_dup`, but it aggressively `#dup`'s class names
286
- # too. These model names should not be `#dup`'ed or we might break ActiveModel::Naming.
285
+ # Note: Rails provides `#deep_dup`, but it aggressively `#dup`'s class names too, turning them
286
+ # into anonymous class instances.
287
287
  def deep_copy
288
- deep_dup.tap do |copy|
289
- %w(repository_class response_model document_model document_presenter_class search_builder_class facet_paginator_class).each do |klass|
290
- # Don't copy if nil, so as not to prematurely autoload default classes
291
- copy.send("#{klass}=", send(klass)) unless fetch(klass.to_sym, nil).nil?
292
- end
293
- end
288
+ deep_transform_values_in_object(self, &method(:_deep_copy))
294
289
  end
295
290
 
296
291
  # builds a copy for the provided controller class
@@ -402,5 +397,37 @@ module Blacklight
402
397
  yield(config) if block_given?
403
398
  config_hash[name] = config
404
399
  end
400
+
401
+ # Provide custom duplication for certain types of configuration (intended for use in e.g. deep_transform_values)
402
+ def _deep_copy(value)
403
+ case value
404
+ when Module then value
405
+ when NestedOpenStructWithHashAccess then value.class.new(value.nested_class, deep_transform_values_in_object(value.to_h, &method(:_deep_copy)))
406
+ when OpenStruct then value.class.new(deep_transform_values_in_object(value.to_h, &method(:_deep_copy)))
407
+ else
408
+ value.dup
409
+ end
410
+ end
411
+
412
+ # This is a little shim to support Rails 6 (which has Hash#deep_transform_values) and
413
+ # earlier versions (which use our backport). Once we drop support for Rails 6, this
414
+ # can go away.
415
+ def deep_transform_values_in_object(object, &block)
416
+ return object.deep_transform_values(&block) if object.respond_to?(:deep_transform_values)
417
+
418
+ _deep_transform_values_in_object(object, &block)
419
+ end
420
+
421
+ # Ported from Rails 6
422
+ def _deep_transform_values_in_object(object, &block)
423
+ case object
424
+ when Hash
425
+ object.transform_values { |value| _deep_transform_values_in_object(value, &block) }
426
+ when Array
427
+ object.map { |e| _deep_transform_values_in_object(e, &block) }
428
+ else
429
+ yield(object)
430
+ end
431
+ end
405
432
  end
406
433
  end
@@ -84,7 +84,7 @@ class <%= controller_name.classify %>Controller < ApplicationController
84
84
  config.add_facet_field 'subject_geo_ssim', label: 'Region'
85
85
  config.add_facet_field 'subject_era_ssim', label: 'Era'
86
86
 
87
- config.add_facet_field 'example_pivot_field', label: 'Pivot Field', :pivot => ['format', 'language_ssim']
87
+ config.add_facet_field 'example_pivot_field', label: 'Pivot Field', pivot: ['format', 'language_ssim'], collapsing: true
88
88
 
89
89
  config.add_facet_field 'example_query_facet_field', label: 'Publish Date', :query => {
90
90
  :years_5 => { label: 'within 5 Years', fq: "pub_date_ssim:[#{Time.zone.now.year - 5 } TO *]" },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blacklight-frontend",
3
- "version": "7.1.0",
3
+ "version": "7.7.0",
4
4
  "lockfileVersion": 1,
5
5
  "requires": true,
6
6
  "dependencies": {
@@ -1884,9 +1884,9 @@
1884
1884
  "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
1885
1885
  },
1886
1886
  "jquery": {
1887
- "version": "3.4.1",
1888
- "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz",
1889
- "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw=="
1887
+ "version": "3.5.1",
1888
+ "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.5.1.tgz",
1889
+ "integrity": "sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg=="
1890
1890
  },
1891
1891
  "js-tokens": {
1892
1892
  "version": "4.0.0",
@@ -24,7 +24,7 @@
24
24
  "dependencies": {
25
25
  "bloodhound-js": "^1.2.3",
26
26
  "bootstrap": "^4.3.1",
27
- "jquery": "^3.4.1",
27
+ "jquery": "^3.5.1",
28
28
  "typeahead.js": "^0.11.1"
29
29
  }
30
30
  }
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Blacklight::FacetItemPivotComponent, type: :component do
6
+ subject(:render) do
7
+ render_inline(described_class.new(facet_item: facet_item))
8
+ end
9
+
10
+ let(:rendered) do
11
+ Capybara::Node::Simple.new(render)
12
+ end
13
+
14
+ let(:search_state) do
15
+ Blacklight::SearchState.new({}, Blacklight::Configuration.new)
16
+ end
17
+
18
+ let(:facet_item) do
19
+ instance_double(
20
+ Blacklight::FacetItemPresenter,
21
+ facet_config: Blacklight::Configuration::FacetField.new(key: 'z'),
22
+ facet_field: 'z',
23
+ label: 'x',
24
+ hits: 10,
25
+ href: '/catalog?f[z]=x',
26
+ selected?: false,
27
+ search_state: search_state,
28
+ items: [OpenStruct.new(value: 'x:1', hits: 5)]
29
+ )
30
+ end
31
+
32
+ it 'links to the facet and shows the number of hits' do
33
+ expect(rendered).to have_selector 'li'
34
+ expect(rendered).to have_link 'x', href: '/catalog?f[z]=x'
35
+ expect(rendered).to have_selector '.facet-count', text: '10'
36
+ end
37
+
38
+ it 'has the facet hierarchy' do
39
+ puts render
40
+ expect(rendered).to have_selector 'li ul.pivot-facet'
41
+ expect(rendered).to have_link 'x:1', href: /f%5Bz%5D%5B%5D=x%3A1/
42
+ end
43
+
44
+ context 'with a selected facet' do
45
+ let(:facet_item) do
46
+ instance_double(
47
+ Blacklight::FacetItemPresenter,
48
+ facet_config: Blacklight::Configuration::FacetField.new,
49
+ facet_field: 'z',
50
+ label: 'x',
51
+ hits: 10,
52
+ href: '/catalog',
53
+ selected?: true,
54
+ search_state: search_state,
55
+ items: []
56
+ )
57
+ end
58
+
59
+ it 'links to the facet and shows the number of hits' do
60
+ expect(rendered).to have_selector 'li'
61
+ expect(rendered).to have_selector '.selected', text: 'x'
62
+ expect(rendered).to have_link '[remove]', href: '/catalog'
63
+ expect(rendered).to have_selector '.selected.facet-count', text: '10'
64
+ end
65
+ end
66
+ end
@@ -67,6 +67,26 @@ RSpec.describe "Facets" do
67
67
  expect(page).to have_css('#facet-format', visible: true) # assert that it didn't re-collapse
68
68
  end
69
69
 
70
+ it 'is able to expand pivot facets when javascript is enabled', js: true do
71
+ visit root_path
72
+
73
+ within('#facets .facets-header') do
74
+ page.find('button.navbar-toggler').click
75
+ end
76
+
77
+ page.find('h3.facet-field-heading button', text: 'Pivot Field').click
78
+
79
+ within '#facet-example_pivot_field' do
80
+ expect(page).to have_css('.facet-leaf-node', text: 'Book 30')
81
+ expect(page).not_to have_css('.facet-select', text: 'Tibetan')
82
+ page.find('.facet-toggle-handle').click
83
+ click_link 'Tibetan'
84
+ end
85
+
86
+ expect(page).to have_css('.constraint-value', text: 'Format Book')
87
+ expect(page).to have_css('.constraint-value', text: 'Language Tibetan')
88
+ end
89
+
70
90
  describe 'heading button focus with Firefox' do
71
91
  before do
72
92
  Capybara.current_driver = :selenium_headless
@@ -189,14 +189,18 @@ RSpec.describe "Blacklight::Configuration", api: true do
189
189
  it "provides cloned copies of mutable data structures" do
190
190
  config.a = { value: 1 }
191
191
  config.b = [1, 2, 3]
192
+ config.c = Blacklight::Configuration::Field.new(key: 'c', value: %w[a b])
192
193
 
193
194
  config_copy.a[:value] = 2
194
195
  config_copy.b << 5
196
+ config_copy.c.value << 'c'
195
197
 
196
198
  expect(config.a[:value]).to eq 1
197
199
  expect(config_copy.a[:value]).to eq 2
198
200
  expect(config.b).to match_array [1, 2, 3]
199
201
  expect(config_copy.b).to match_array [1, 2, 3, 5]
202
+ expect(config.c.value).to match_array %w[a b]
203
+ expect(config_copy.c.value).to match_array %w[a b c]
200
204
  end
201
205
  end
202
206
 
@@ -17,22 +17,14 @@ RSpec.describe Blacklight::Icon do
17
17
  end
18
18
  it 'adds title' do
19
19
  expect(Capybara.string(subject.svg))
20
- .to have_css 'title[id^="bl-icon-search-"]', text: 'search icon'
21
- end
22
- it 'adds aria-labelledby' do
23
- expect(Capybara.string(subject.svg))
24
- .to have_css 'svg[aria-labelledby^="bl-icon-search-"]'
20
+ .to have_css 'title', text: 'Search'
25
21
  end
26
22
  context 'when label is false' do
27
23
  subject { described_class.new(:search, classes: 'awesome', aria_hidden: true, label: false) }
28
24
 
29
25
  it 'does not add title' do
30
26
  expect(Capybara.string(subject.svg))
31
- .not_to have_css 'title', text: 'search icon'
32
- end
33
- it 'does not add aria-labelledby' do
34
- expect(Capybara.string(subject.svg))
35
- .not_to have_css 'svg[aria-labelledby^="bl-icon-search-"]'
27
+ .not_to have_css 'title', text: 'Search'
36
28
  end
37
29
  end
38
30
 
@@ -41,14 +33,14 @@ RSpec.describe Blacklight::Icon do
41
33
 
42
34
  it 'adds title' do
43
35
  expect(Capybara.string(subject.svg))
44
- .to have_css 'title[id^="bl-icon-search_foo-"]', text: 'search icon'
36
+ .to have_css 'title', text: 'Search'
45
37
  end
46
38
  end
47
39
  end
48
40
 
49
41
  describe '#options' do
50
42
  it 'applies options classes and default class' do
51
- expect(subject.options[:class]).to eq 'blacklight-icons awesome'
43
+ expect(subject.options[:class]).to eq 'blacklight-icons blacklight-icon-search awesome'
52
44
  end
53
45
  it 'applies options aria-hidden=true' do
54
46
  expect(subject.options[:'aria-hidden']).to be true
@@ -57,7 +49,7 @@ RSpec.describe Blacklight::Icon do
57
49
  subject { described_class.new(:view) }
58
50
 
59
51
  it 'applies default class with no options' do
60
- expect(subject.options[:class]).to eq 'blacklight-icons'
52
+ expect(subject.options[:class]).to eq 'blacklight-icons blacklight-icon-view'
61
53
  end
62
54
 
63
55
  it 'has no aria-hidden attribute with no options' do
@@ -25,6 +25,7 @@ require 'equivalent-xml'
25
25
  require 'webdrivers'
26
26
 
27
27
  Capybara.javascript_driver = :selenium_chrome_headless
28
+ Capybara.disable_animation = true
28
29
 
29
30
  # Requires supporting ruby files with custom matchers and macros, etc,
30
31
  # in spec/support/ and its subdirectories.
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.8.1
4
+ version: 7.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Rochkind
@@ -17,7 +17,7 @@ authors:
17
17
  autorequire:
18
18
  bindir: exe
19
19
  cert_chain: []
20
- date: 2020-06-01 00:00:00.000000000 Z
20
+ date: 2020-06-23 00:00:00.000000000 Z
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency
23
23
  name: rails
@@ -360,6 +360,7 @@ files:
360
360
  - app/components/blacklight/facet_field_list_component.rb
361
361
  - app/components/blacklight/facet_field_no_layout_component.rb
362
362
  - app/components/blacklight/facet_item_component.rb
363
+ - app/components/blacklight/facet_item_pivot_component.rb
363
364
  - app/controllers/bookmarks_controller.rb
364
365
  - app/controllers/catalog_controller.rb
365
366
  - app/controllers/concerns/blacklight/base.rb
@@ -624,6 +625,7 @@ files:
624
625
  - spec/components/blacklight/constraint_layout_component_spec.rb
625
626
  - spec/components/blacklight/facet_field_list_component_spec.rb
626
627
  - spec/components/blacklight/facet_item_component_spec.rb
628
+ - spec/components/blacklight/facet_item_pivot_component_spec.rb
627
629
  - spec/controllers/alternate_controller_spec.rb
628
630
  - spec/controllers/application_controller_spec.rb
629
631
  - spec/controllers/blacklight/base_spec.rb
@@ -780,6 +782,7 @@ test_files:
780
782
  - spec/components/blacklight/constraint_layout_component_spec.rb
781
783
  - spec/components/blacklight/facet_field_list_component_spec.rb
782
784
  - spec/components/blacklight/facet_item_component_spec.rb
785
+ - spec/components/blacklight/facet_item_pivot_component_spec.rb
783
786
  - spec/controllers/alternate_controller_spec.rb
784
787
  - spec/controllers/application_controller_spec.rb
785
788
  - spec/controllers/blacklight/base_spec.rb