blacklight 7.14.1 → 7.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/app/components/blacklight/advanced_search_form_component.html.erb +46 -0
  4. data/app/components/blacklight/advanced_search_form_component.rb +75 -0
  5. data/app/components/blacklight/constraint_component.html.erb +1 -1
  6. data/app/components/blacklight/constraints_component.rb +36 -17
  7. data/app/components/blacklight/document/thumbnail_component.html.erb +1 -1
  8. data/app/components/blacklight/document/thumbnail_component.rb +4 -1
  9. data/app/components/blacklight/document_component.rb +7 -2
  10. data/app/components/blacklight/facet_field_checkboxes_component.html.erb +23 -0
  11. data/app/components/blacklight/facet_field_checkboxes_component.rb +24 -0
  12. data/app/components/blacklight/facet_field_inclusive_constraint_component.html.erb +6 -0
  13. data/app/components/blacklight/facet_field_inclusive_constraint_component.rb +29 -0
  14. data/app/components/blacklight/facet_field_list_component.html.erb +1 -0
  15. data/app/components/blacklight/facet_item_component.rb +2 -0
  16. data/app/components/blacklight/search_bar_component.html.erb +4 -0
  17. data/app/components/blacklight/search_bar_component.rb +4 -2
  18. data/app/controllers/concerns/blacklight/catalog.rb +6 -0
  19. data/app/helpers/blacklight/render_constraints_helper_behavior.rb +2 -2
  20. data/app/presenters/blacklight/clause_presenter.rb +37 -0
  21. data/app/presenters/blacklight/document_presenter.rb +5 -1
  22. data/app/presenters/blacklight/facet_field_presenter.rb +4 -0
  23. data/app/presenters/blacklight/facet_grouped_item_presenter.rb +45 -0
  24. data/app/presenters/blacklight/facet_item_presenter.rb +32 -20
  25. data/app/presenters/blacklight/inclusive_facet_item_presenter.rb +16 -0
  26. data/app/presenters/blacklight/search_bar_presenter.rb +4 -0
  27. data/app/views/catalog/_advanced_search_form.html.erb +7 -0
  28. data/app/views/catalog/_advanced_search_help.html.erb +24 -0
  29. data/app/views/catalog/_search_form.html.erb +1 -0
  30. data/app/views/catalog/advanced_search.html.erb +17 -0
  31. data/blacklight.gemspec +1 -1
  32. data/config/i18n-tasks.yml +1 -0
  33. data/config/locales/blacklight.en.yml +17 -0
  34. data/lib/blacklight/configuration.rb +2 -1
  35. data/lib/blacklight/routes/searchable.rb +1 -0
  36. data/lib/blacklight/search_builder.rb +2 -0
  37. data/lib/blacklight/search_state.rb +5 -1
  38. data/lib/blacklight/search_state/filter_field.rb +17 -7
  39. data/lib/blacklight/solr/repository.rb +11 -2
  40. data/lib/blacklight/solr/search_builder_behavior.rb +87 -23
  41. data/spec/components/blacklight/advanced_search_form_component_spec.rb +51 -0
  42. data/spec/components/blacklight/document_component_spec.rb +15 -0
  43. data/spec/components/blacklight/facet_field_checkboxes_component_spec.rb +55 -0
  44. data/spec/components/blacklight/facet_field_list_component_spec.rb +39 -4
  45. data/spec/controllers/catalog_controller_spec.rb +9 -0
  46. data/spec/features/advanced_search_spec.rb +67 -0
  47. data/spec/lib/blacklight/search_state/filter_field_spec.rb +65 -0
  48. data/spec/models/blacklight/solr/repository_spec.rb +12 -0
  49. data/spec/models/blacklight/solr/search_builder_spec.rb +28 -0
  50. data/spec/presenters/blacklight/clause_presenter_spec.rb +34 -0
  51. data/spec/presenters/blacklight/document_presenter_spec.rb +13 -0
  52. data/spec/presenters/blacklight/facet_grouped_item_presenter_spec.rb +41 -0
  53. metadata +29 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f0fa09c963759adb956f189243824f10d2c16ee518849c33ed0e6343240dec93
4
- data.tar.gz: 61d5a9c3f582555de951e49a1912ad7a4feceb16f2635f1650eafa7a2200be39
3
+ metadata.gz: 8cb69c90e780b277faa807c99cf35b99d2ad0e04b68fd3c56f36a6c170eb8112
4
+ data.tar.gz: d5d7f85ff7af44d193e93a041a658a332a2d0ae31d9dd362f2000135e97ad54d
5
5
  SHA512:
6
- metadata.gz: 9ed401d79a83ca244fd44f3d5ecc08e45a57ec69d76e84265dec12b450594e228906a3db51eb7d2c38560e5ed6a3d643c0ecf16eea9941eb0830cbc64f88294c
7
- data.tar.gz: 90388ff2eab28a18cf4810769995b18143badd8c325b00ad075dbef243d5b3b074de5bb7442c65f6905f009485feca10452ff7b9c4d749b453e7b28da2a3a21d
6
+ metadata.gz: 9e8369e2769bb01b1388da32990b3a4868a14a9214ac070a6827871f5aa8a3659804cf0c11eb53b5f3d49a8f5925fafbd063be53977d1159cfa6f24954762771
7
+ data.tar.gz: 91046b20b9d00fc7cbe8a2f65f888e6a3e891fbf33230b203d0f4f7dc8d1a6d8317acdeec6d067f284bd47ecc51e469c0b6999a053816eec75fde5b7328b526a
data/VERSION CHANGED
@@ -1 +1 @@
1
- 7.14.1
1
+ 7.15.0
@@ -0,0 +1,46 @@
1
+ <% if constraints.present? %>
2
+ <div class="constraints well search_history">
3
+ <h4><%= t 'blacklight.advanced_search.form.search_context' %></h4>
4
+ <%= constraints %>
5
+ </div>
6
+ <% end %>
7
+
8
+ <%= form_tag @url, method: @method, class: @classes.join(' '), role: 'search', 'aria-label' => t('blacklight.search.form.submit') do %>
9
+ <%= render_hash_as_hidden_fields(@params) %>
10
+
11
+ <div class="input-criteria">
12
+ <div class="query-criteria">
13
+ <h2 class="query-criteria-heading">
14
+ <%= t('blacklight.advanced_search.form.query_criteria_heading_html', select_menu: default_operator_menu) %>
15
+ </h2>
16
+
17
+ <div id="advanced_search">
18
+ <%= search_field_controls %>
19
+ </div>
20
+ </div>
21
+
22
+ <div class="limit-criteria">
23
+ <h2 class="limit-criteria-heading"><%= t('blacklight.advanced_search.form.limit_criteria_heading_html')%></h2>
24
+
25
+ <div id="advanced_search_facets" class="limit_input">
26
+ <div class="advanced-facet-limits panel-group">
27
+ <%= search_filter_controls %>
28
+ </div>
29
+ </div>
30
+ </div>
31
+ </div>
32
+
33
+ <%= content_tag :h2, t('blacklight.advanced_search.form.sort_label') %>
34
+ <div class="form-group row">
35
+ <div class="col-sm-offset-3 col-sm-4">
36
+ <%= sort_fields_select %>
37
+ </div>
38
+ </div>
39
+
40
+ <div class="form-group row">
41
+ <div class="submit-buttons col-sm-offset-3 col-sm-9">
42
+ <%= submit_tag t('blacklight.advanced_search.form.search_btn_html'), class: 'btn btn-primary advanced-search-submit', id: "advanced-search-submit" %>
43
+ <%= button_tag t('blacklight.advanced_search.form.start_over_html'), type: 'reset', class: 'btn btn-link advanced-search-start-over' %>
44
+ </div>
45
+ </div>
46
+ <% end %>
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ class AdvancedSearchFormComponent < SearchBarComponent
5
+ with_content_areas :constraints, :search_field_controls, :search_filter_controls
6
+
7
+ def initialize(response:, **options)
8
+ super(**options)
9
+ @response = response
10
+ end
11
+
12
+ def default_operator_menu
13
+ options_with_labels = [:must, :should].index_by { |op| t(op, scope: 'blacklight.advanced_search.op') }
14
+ select_tag(:op, options_for_select(options_with_labels, params[:op]), class: 'input-small')
15
+ end
16
+
17
+ # Rubocop is just wrong here, so...:
18
+ # rubocop:disable Rails/ContentTag
19
+ def search_field_controls
20
+ @search_field_controls || safe_join(search_fields.values.map.with_index do |field, i|
21
+ fields_for('clause[]', i, include_id: false) do |f|
22
+ content_tag(:div, class: 'form-group advanced-search-field row') do
23
+ f.label(:query, field.display_label('search'), class: "col-sm-3 col-form-label") +
24
+ content_tag(:div, class: 'col-sm-9') do
25
+ f.hidden_field(:field, value: field.key) +
26
+ f.text_field(:query, value: query_for_search_clause(field.key), class: 'form-control')
27
+ end
28
+ end
29
+ end
30
+ end, "\n")
31
+ end
32
+ # rubocop:enable Rails/ContentTag
33
+
34
+ def query_for_search_clause(key)
35
+ field = (@params[:clause] || {}).values.find { |value| value['field'].to_s == key.to_s }
36
+
37
+ field&.dig('query')
38
+ end
39
+
40
+ def search_filter_controls
41
+ return @search_filter_controls if @search_filter_controls
42
+
43
+ fields = blacklight_config.facet_fields.select { |_k, v| v.include_in_advanced_search || v.include_in_advanced_search.nil? }
44
+
45
+ safe_join(fields.map do |_k, config|
46
+ display_facet = @response.aggregations[config.field]
47
+
48
+ presenter = (config.presenter || Blacklight::FacetFieldPresenter).new(config, display_facet, @view_context)
49
+ component = config.advanced_search_component || Blacklight::FacetFieldCheckboxesComponent
50
+ @view_context.render(component.new(facet_field: presenter))
51
+ end, "\n")
52
+ end
53
+
54
+ def constraints
55
+ params = @view_context.search_state.params_for_search.except :page, :f_inclusive, :q, :search_field, :op, :index, :sort
56
+
57
+ params.except!(*search_fields.map { |_key, field_def| field_def[:key] })
58
+
59
+ @view_context.render_search_to_s(params)
60
+ end
61
+
62
+ def sort_fields_select
63
+ options = sort_fields.values.map { |field_config| [@view_context.sort_field_label(field_config.key), field_config.key] }
64
+ select_tag(:sort, options_for_select(options, params[:sort]), class: "form-control sort-select")
65
+ end
66
+
67
+ def search_fields
68
+ blacklight_config.search_fields.select { |_k, v| v.include_in_advanced_search || v.include_in_advanced_search.nil? }
69
+ end
70
+
71
+ def sort_fields
72
+ blacklight_config.sort_fields.select { |_k, v| v.include_in_advanced_search || v.include_in_advanced_search.nil? }
73
+ end
74
+ end
75
+ end
@@ -1,5 +1,5 @@
1
1
  <%= render(@layout.new(
2
- classes: (Array(@classes) + ["filter-#{@facet_item_presenter.facet_config.key.parameterize}"]).join(' '),
2
+ classes: (Array(@classes) + ["filter-#{@facet_item_presenter.key.parameterize}"]).join(' '),
3
3
  label: @facet_item_presenter.field_label,
4
4
  value: @facet_item_presenter.label,
5
5
  remove_path: @facet_item_presenter.remove_href)) %>
@@ -15,23 +15,25 @@ module Blacklight
15
15
  end
16
16
 
17
17
  def query_constraints
18
- return if @search_state.query_param.blank?
19
-
20
18
  Deprecation.silence(Blacklight::RenderConstraintsHelperBehavior) do
21
- @view_context.render(
22
- @query_constraint_component.new(
23
- search_state: @search_state,
24
- value: @search_state.query_param,
25
- label: label,
26
- remove_path: @view_context.remove_constraint_url(@search_state),
27
- classes: 'query'
19
+ if @search_state.query_param.present?
20
+ @view_context.render(
21
+ @query_constraint_component.new(
22
+ search_state: @search_state,
23
+ value: @search_state.query_param,
24
+ label: label,
25
+ remove_path: @view_context.remove_constraint_url(@search_state),
26
+ classes: 'query'
27
+ )
28
28
  )
29
- )
30
- end
29
+ else
30
+ ''.html_safe
31
+ end
32
+ end + @view_context.render(@facet_constraint_component.with_collection(clause_presenters.to_a))
31
33
  end
32
34
 
33
35
  def facet_constraints
34
- @view_context.render(@facet_constraint_component.with_collection(facet_item_presenters))
36
+ @view_context.render(@facet_constraint_component.with_collection(facet_item_presenters.to_a))
35
37
  end
36
38
 
37
39
  def start_over_path
@@ -53,21 +55,38 @@ module Blacklight
53
55
  end
54
56
 
55
57
  def facet_item_presenters
56
- Deprecation.silence(Blacklight::SearchState) do
57
- @search_state.filter_params.each_pair.flat_map do |facet, values|
58
- facet_config = @view_context.facet_configuration_for_field(facet)
58
+ return to_enum(:facet_item_presenters) unless block_given?
59
59
 
60
- Array(values).map do |val|
60
+ Deprecation.silence(Blacklight::SearchState) do
61
+ @search_state.filters.map do |facet|
62
+ facet.values.map do |val|
61
63
  next if val.blank? # skip empty string
62
64
 
63
- facet_item_presenter(facet_config, val, facet)
65
+ if val.is_a?(Array)
66
+ yield inclusive_facet_item_presenter(facet.config, val, facet.key) if val.any?(&:present?)
67
+ else
68
+ yield facet_item_presenter(facet.config, val, facet.key)
69
+ end
64
70
  end
65
71
  end
66
72
  end
67
73
  end
68
74
 
75
+ def clause_presenters
76
+ return to_enum(:clause_presenters) unless block_given?
77
+
78
+ @search_state.clause_params.each do |key, clause|
79
+ field_config = @view_context.blacklight_config.search_fields[clause[:field]]
80
+ yield Blacklight::ClausePresenter.new(key, clause, field_config, @view_context)
81
+ end
82
+ end
83
+
69
84
  def facet_item_presenter(facet_config, facet_item, facet_field)
70
85
  Blacklight::FacetItemPresenter.new(facet_item, facet_config, @view_context, facet_field)
71
86
  end
87
+
88
+ def inclusive_facet_item_presenter(facet_config, facet_item, facet_field)
89
+ Blacklight::InclusiveFacetItemPresenter.new(facet_item, facet_config, @view_context, facet_field)
90
+ end
72
91
  end
73
92
  end
@@ -1,4 +1,4 @@
1
- <% value = @use_thumbnail_tag ? @presenter.thumbnail.thumbnail_tag({ alt: '' }, 'aria-hidden': true, tabindex: -1, counter: @counter) : @presenter.thumbnail.render({ alt: '' }) %>
1
+ <% value = @use_thumbnail_tag ? @presenter.thumbnail.thumbnail_tag(@image_options, 'aria-hidden': true, tabindex: -1, counter: @counter) : @presenter.thumbnail.render(@image_options) %>
2
2
 
3
3
  <% if value %>
4
4
  <div class="document-thumbnail">
@@ -7,9 +7,12 @@ module Blacklight
7
7
  with_collection_parameter :presenter
8
8
 
9
9
  # @param [Blacklight::DocumentPresenter] presenter
10
- def initialize(presenter:, counter:)
10
+ # @param [Integer] counter
11
+ # @param [Hash] image_options options for the thumbnail presenter's image tag
12
+ def initialize(presenter:, counter:, image_options: {})
11
13
  @presenter = presenter
12
14
  @counter = counter
15
+ @image_options = { alt: '' }.merge(image_options)
13
16
  @use_thumbnail_tag = !@presenter.thumbnail.instance_of?(Blacklight::ThumbnailPresenter)
14
17
  end
15
18
 
@@ -26,6 +26,7 @@ module Blacklight
26
26
  id: nil, classes: [], component: :article, title_component: :h4,
27
27
  metadata_component: Blacklight::DocumentMetadataComponent,
28
28
  embed_component: nil,
29
+ thumbnail_component: Blacklight::Document::ThumbnailComponent,
29
30
  counter: nil, document_counter: nil, counter_offset: 0,
30
31
  show: false)
31
32
  if presenter.nil? && document.nil?
@@ -42,6 +43,7 @@ module Blacklight
42
43
 
43
44
  @embed_component = embed_component
44
45
  @metadata_component = metadata_component
46
+ @thumbnail_component = thumbnail_component
45
47
 
46
48
  @document_counter = document_counter
47
49
  @counter = counter
@@ -83,11 +85,14 @@ module Blacklight
83
85
  end
84
86
 
85
87
  # Content for the document thumbnail area
86
- def thumbnail
88
+ def thumbnail(image_options = {})
87
89
  return super if block_given?
90
+ return @thumbnail if @thumbnail
91
+
88
92
  return if @show
89
93
 
90
- @thumbnail || render(Blacklight::Document::ThumbnailComponent.new(presenter: presenter, counter: @counter))
94
+ component = @thumbnail_component || presenter.view_config.thumbnail_component
95
+ render(component.new(presenter: presenter, counter: @counter, image_options: image_options))
91
96
  end
92
97
 
93
98
  # Content for the document metadata area
@@ -0,0 +1,23 @@
1
+ <%= render(@layout.new(facet_field: @facet_field)) do |component| %>
2
+ <% component.with(:label) do %>
3
+ <%= @facet_field.label %>
4
+ <% end %>
5
+
6
+ <% component.with(:body) do %>
7
+ <ul class="facet-values list-unstyled blacklight-facet-checkboxes">
8
+ <% presenters.each_with_index do |presenter, idx| -%>
9
+ <li>
10
+ <span class="facet-checkbox">
11
+ <%= check_box_tag "f_inclusive[#{@facet_field.key}][]", presenter.value, presenter.selected?, id: "f_inclusive_#{@facet_field.key}_#{idx}"%>
12
+ </span>
13
+
14
+ <span class="label-and-count">
15
+ <%= label_tag "f_inclusive_#{@facet_field.key}_#{idx}" do %>
16
+ <%= presenter.label %>
17
+ <% end %>
18
+ <span>
19
+ </li>
20
+ <% end -%>
21
+ </ul>
22
+ <% end %>
23
+ <% end %>
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ class FacetFieldCheckboxesComponent < ::ViewComponent::Base
5
+ def initialize(facet_field:, layout: nil)
6
+ @facet_field = facet_field
7
+ @layout = layout == false ? FacetFieldNoLayoutComponent : Blacklight::FacetFieldComponent
8
+ end
9
+
10
+ def render?
11
+ presenters.any?
12
+ end
13
+
14
+ def presenters
15
+ return [] unless @facet_field.paginator
16
+
17
+ return to_enum(:presenters) unless block_given?
18
+
19
+ @facet_field.paginator.items.each do |item|
20
+ yield Blacklight::FacetItemPresenter.new(item, @facet_field.facet_field, @view_context, @facet_field.key, @facet_field.search_state)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,6 @@
1
+ <div class="inclusive_or card card-body bg-light mb-3">
2
+ <h5><%= t('blacklight.advanced_search.any_of') %></h5>
3
+ <ul class="list-unstyled facet-values">
4
+ <%= @view_context.render(Blacklight::FacetItemComponent.with_collection(presenters.to_a)) %>
5
+ </ul>
6
+ </div>
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ class FacetFieldInclusiveConstraintComponent < ::ViewComponent::Base
5
+ with_collection_parameter :facet_field
6
+
7
+ def initialize(facet_field:, values: nil)
8
+ @facet_field = facet_field
9
+ @values = values
10
+ end
11
+
12
+ def values
13
+ @values ||= @facet_field.values.find { |v| v.is_a? Array }
14
+ @values || []
15
+ end
16
+
17
+ def render?
18
+ values.present?
19
+ end
20
+
21
+ def presenters
22
+ return to_enum(:presenters) unless block_given?
23
+
24
+ values.each do |item|
25
+ yield Blacklight::FacetGroupedItemPresenter.new(values, item, @facet_field.facet_field, @view_context, @facet_field.key, @facet_field.search_state)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -3,6 +3,7 @@
3
3
  <%= @facet_field.label %>
4
4
  <% end %>
5
5
  <% component.with(:body) do %>
6
+ <%= @view_context.render(Blacklight::FacetFieldInclusiveConstraintComponent.new(facet_field: @facet_field)) %>
6
7
  <ul class="facet-values list-unstyled">
7
8
  <%= render_facet_limit_list @facet_field.paginator, @facet_field.key %>
8
9
  </ul>
@@ -103,6 +103,8 @@ module Blacklight
103
103
  def render_facet_count(options = {})
104
104
  return @view_context.render_facet_count(@hits, options) unless @view_context.method(:render_facet_count).owner == Blacklight::FacetsHelperBehavior || explicit_component_configuration?
105
105
 
106
+ return '' if @hits.blank?
107
+
106
108
  classes = (options[:classes] || []) << "facet-count"
107
109
  tag.span(t('blacklight.search.facets.count', number: number_with_delimiter(@hits)), class: classes)
108
110
  end
@@ -29,3 +29,7 @@
29
29
  </span>
30
30
  </div>
31
31
  <% end %>
32
+
33
+ <% if presenter.advanced_search_enabled? %>
34
+ <%= link_to t('blacklight.advanced_search.more_options'), @advanced_search_url, class: 'advanced_search btn btn-secondary'%>
35
+ <% end %>
@@ -6,12 +6,14 @@ module Blacklight
6
6
 
7
7
  # rubocop:disable Metrics/ParameterLists
8
8
  def initialize(
9
- url:, params:, classes: ['search-query-form'], presenter: nil,
10
- prefix: '', method: 'GET', q: nil, query_param: :q,
9
+ url:, advanced_search_url: nil, params:,
10
+ classes: ['search-query-form'], presenter: nil, prefix: '',
11
+ method: 'GET', q: nil, query_param: :q,
11
12
  search_field: nil, search_fields: [], autocomplete_path: nil,
12
13
  autofocus: nil, i18n: { scope: 'blacklight.search.form' }
13
14
  )
14
15
  @url = url
16
+ @advanced_search_url = advanced_search_url
15
17
  @q = q || params[:q]
16
18
  @query_param = query_param
17
19
  @search_field = search_field || params[:search_field]
@@ -56,6 +56,12 @@ module Blacklight::Catalog
56
56
  end
57
57
  end
58
58
 
59
+ def advanced_search
60
+ empty_service = search_service_class.new(config: blacklight_config, user_params: {}, **search_service_context)
61
+
62
+ (@response, _deprecated_document_list) = empty_service.search_results
63
+ end
64
+
59
65
  # get a single document from the index
60
66
  def raw
61
67
  raise(ActionController::RoutingError, 'Not Found') unless blacklight_config.raw_endpoint.enabled
@@ -88,8 +88,8 @@ module Blacklight::RenderConstraintsHelperBehavior
88
88
  return "".html_safe if search_state.filter_params.blank?
89
89
 
90
90
  Deprecation.silence(Blacklight::RenderConstraintsHelperBehavior) do
91
- safe_join(search_state.filter_params.each_pair.map do |facet, values|
92
- render_filter_element(facet, values, search_state)
91
+ safe_join(search_state.filters.map do |field|
92
+ render_filter_element(field.key, field.values, search_state)
93
93
  end, "\n")
94
94
  end
95
95
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Blacklight
4
+ class ClausePresenter
5
+ attr_reader :key, :user_parameters, :field_config, :view_context, :search_state
6
+
7
+ def initialize(key, user_parameters, field_config, view_context, search_state = view_context.search_state)
8
+ @key = key
9
+ @user_parameters = user_parameters
10
+ @field_config = field_config
11
+ @view_context = view_context
12
+ @search_state = search_state
13
+ end
14
+
15
+ def field_label
16
+ field_config.display_label('search')
17
+ end
18
+
19
+ ##
20
+ # Get the displayable version of a facet's value
21
+ #
22
+ # @return [String]
23
+ def label
24
+ user_parameters[:query]
25
+ end
26
+
27
+ def remove_href(path = search_state)
28
+ view_context.search_action_path(path.reset_search(clause: path.clause_params.except(key)))
29
+ end
30
+
31
+ private
32
+
33
+ def facet_field_presenter
34
+ @facet_field_presenter ||= view_context.facet_field_presenter(facet_config, {})
35
+ end
36
+ end
37
+ end