Skip to content

Commit c11db26

Browse files
committed
Start migrating constraints towards using view components
1 parent 8b86f9e commit c11db26

File tree

9 files changed

+189
-91
lines changed

9 files changed

+189
-91
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<span class="btn-group applied-filter constraint <%= @classes %>">
2+
<span class="constraint-value btn btn-outline-secondary btn-disabled">
3+
<% if @label.present? %>
4+
<span class="filter-name"><%= @label %></span>
5+
<% end %>
6+
<% if @value.present? %>
7+
<%= content_tag :span, @value, class: 'filter-value', title: strip_tags(@value) %>
8+
<% end %>
9+
</span>
10+
<% if @remove_path.present? %>
11+
<%= link_to(@remove_path, class: 'btn btn-outline-secondary remove') do %>
12+
<span class="remove-icon"></span>
13+
<%= if @label.blank?
14+
t('blacklight.search.filters.remove.value', value: @value)
15+
else
16+
t('blacklight.search.filters.remove.label_value', label: @label, value: @value)
17+
end
18+
%>
19+
<% end %>
20+
<% end %>
21+
</span>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# frozen_string_literal: true
2+
3+
module Blacklight
4+
class ConstraintLayoutComponent < ::ViewComponent::Base
5+
def initialize(value:, label: nil, remove_path: nil, classes: nil)
6+
@value = value
7+
@label = label
8+
@remove_path = remove_path
9+
@classes = Array(classes).join(' ')
10+
end
11+
12+
def render?
13+
@value.present?
14+
end
15+
end
16+
end

app/helpers/blacklight/render_constraints_helper_behavior.rb

+61-32
Original file line numberDiff line numberDiff line change
@@ -6,39 +6,57 @@
66
# Includes methods for rendering contraints graphically on the
77
# search results page (render_constraints(_*))
88
module Blacklight::RenderConstraintsHelperBehavior
9+
extend Deprecation
10+
self.deprecation_horizon = 'blacklight 8.0'
11+
912
##
1013
# Check if the query has any constraints defined (a query, facet, etc)
1114
#
1215
# @param [Hash] localized_params query parameters
1316
# @return [Boolean]
14-
def query_has_constraints?(localized_params = params)
15-
!(localized_params[:q].blank? && localized_params[:f].blank?)
17+
def query_has_constraints?(params_or_search_state = search_state)
18+
search_state = convert_to_search_state(params_or_search_state)
19+
search_state.has_constraints?
1620
end
21+
deprecation_deprecate :query_has_constraints?
1722

1823
##
1924
# Render the actual constraints, not including header or footer
2025
# info.
2126
#
2227
# @param [Hash] localized_params query parameters
2328
# @return [String]
24-
def render_constraints(localized_params = params)
25-
render_constraints_query(localized_params) + render_constraints_filters(localized_params)
29+
def render_constraints(localized_params = params, local_search_state = search_state)
30+
params_or_search_state = if localized_params != params
31+
localized_params
32+
else
33+
local_search_state
34+
end
35+
36+
Deprecation.silence(Blacklight::RenderConstraintsHelperBehavior) do
37+
render_constraints_query(params_or_search_state) + render_constraints_filters(params_or_search_state)
38+
end
2639
end
2740

2841
##
2942
# Render the query constraints
3043
#
3144
# @param [ActionController::Parameters] localized_params query parameters
3245
# @return [String]
33-
def render_constraints_query(localized_params = params)
46+
def render_constraints_query(params_or_search_state = search_state)
47+
search_state = convert_to_search_state(params_or_search_state)
48+
3449
# So simple don't need a view template, we can just do it here.
35-
return "".html_safe if localized_params[:q].blank?
50+
return "".html_safe if search_state.query_param.blank?
3651

37-
render_constraint_element(constraint_query_label(localized_params),
38-
localized_params[:q],
39-
classes: ["query"],
40-
remove: remove_constraint_url(localized_params))
52+
Deprecation.silence(Blacklight::RenderConstraintsHelperBehavior) do
53+
render_constraint_element(constraint_query_label(search_state),
54+
search_state.query_param,
55+
classes: ["query"],
56+
remove: remove_constraint_url(search_state))
57+
end
4158
end
59+
deprecation_deprecate :render_constraints_query
4260

4361
##
4462
# Provide a url for removing a particular constraint. This can be overriden
@@ -47,54 +65,53 @@ def render_constraints_query(localized_params = params)
4765
#
4866
# @param [ActionController::Parameters] localized_params query parameters
4967
# @return [String]
50-
def remove_constraint_url(localized_params)
51-
scope = localized_params.delete(:route_set) || self
52-
53-
unless localized_params.is_a? ActionController::Parameters
54-
localized_params = ActionController::Parameters.new(localized_params)
55-
end
68+
def remove_constraint_url(params_or_search_state = search_state)
69+
search_state = convert_to_search_state(params_or_search_state)
5670

57-
options = localized_params.merge(q: nil, action: 'index')
58-
options.permit!
59-
scope.url_for(options)
71+
search_action_path(search_state.remove_query_params)
6072
end
73+
deprecation_deprecate :remove_constraint_url
6174

6275
##
6376
# Render the facet constraints
6477
# @param [Hash] localized_params query parameters
6578
# @return [String]
66-
def render_constraints_filters(localized_params = params)
67-
return "".html_safe unless localized_params[:f]
79+
def render_constraints_filters(params_or_search_state = search_state)
80+
search_state = convert_to_search_state(params_or_search_state)
6881

69-
path = controller.search_state_class.new(localized_params, blacklight_config, controller)
70-
content = []
71-
localized_params[:f].each_pair do |facet, values|
72-
content << render_filter_element(facet, values, path)
73-
end
82+
return "".html_safe if search_state.filter_params.blank?
7483

75-
safe_join(content.flatten, "\n")
84+
Deprecation.silence(Blacklight::RenderConstraintsHelperBehavior) do
85+
safe_join(search_state.filter_params.each_pair.map do |facet, values|
86+
render_filter_element(facet, values, search_state)
87+
end, "\n")
88+
end
7689
end
90+
deprecation_deprecate :render_constraints_filters
7791

7892
##
7993
# Render a single facet's constraint
8094
# @param [String] facet field
8195
# @param [Array<String>] values selected facet values
8296
# @param [Blacklight::SearchState] path query parameters (unused)
8397
# @return [String]
84-
def render_filter_element(facet, values, path)
98+
def render_filter_element(facet, values, search_state)
8599
facet_config = facet_configuration_for_field(facet)
86100

87101
safe_join(Array(values).map do |val|
88102
next if val.blank? # skip empty string
89103

90104
presenter = facet_item_presenter(facet_config, val, facet)
91105

92-
render_constraint_element(facet_field_label(facet_config.key),
93-
presenter.label,
94-
remove: presenter.remove_href(path),
95-
classes: ["filter", "filter-" + facet.parameterize])
106+
Deprecation.silence(Blacklight::RenderConstraintsHelperBehavior) do
107+
render_constraint_element(facet_field_label(facet_config.key),
108+
presenter.label,
109+
remove: presenter.remove_href(search_state),
110+
classes: ["filter", "filter-" + facet.parameterize])
111+
end
96112
end, "\n")
97113
end
114+
deprecation_deprecate :render_filter_element
98115

99116
# Render a label/value constraint on the screen. Can be called
100117
# by plugins and such to get application-defined rendering.
@@ -113,4 +130,16 @@ def render_filter_element(facet, values, path)
113130
def render_constraint_element(label, value, options = {})
114131
render(partial: "catalog/constraints_element", locals: { label: label, value: value, options: options })
115132
end
133+
deprecation_deprecate :render_constraint_element
134+
135+
private
136+
137+
def convert_to_search_state(params_or_search_state)
138+
if params_or_search_state.is_a? Blacklight::SearchState
139+
params_or_search_state
140+
else
141+
# deprecated
142+
controller.search_state_class.new(params_or_search_state, blacklight_config, controller)
143+
end
144+
end
116145
end

app/views/catalog/_constraints.html.erb

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44

55
<%= render 'start_over' %>
66
<span class="constraints-label sr-only"><%= t('blacklight.search.filters.title') %></span>
7-
<%= render_constraints(params) %>
7+
<%= render_constraints(controller.params != params ? params : search_state) %>
88
</div>
99
<% end %>

app/views/catalog/_constraints_element.html.erb

+5-24
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,8 @@
77
options ||= {}
88
%>
99

10-
<span class="btn-group applied-filter constraint <%= options[:classes].join(" ") if options[:classes] %>">
11-
<span class="constraint-value btn btn-outline-secondary btn-disabled">
12-
<% unless label.blank? %>
13-
<span class="filter-name"><%= label %></span>
14-
<% end %>
15-
<% unless value.blank? %>
16-
<%= content_tag :span, value, class: 'filter-value', title: strip_tags(value) %>
17-
<% end %>
18-
</span>
19-
<% unless options[:remove].blank? %>
20-
<% accessible_remove_label = content_tag :span, class: 'sr-only' do
21-
if label.blank?
22-
t('blacklight.search.filters.remove.value', value: value)
23-
else
24-
t('blacklight.search.filters.remove.label_value', label: label, value: value)
25-
end
26-
end
27-
%>
28-
29-
<%= link_to(content_tag(:span, '✖', class: 'remove-icon') + accessible_remove_label,
30-
options[:remove], class: 'btn btn-outline-secondary remove'
31-
) %>
32-
<%- end -%>
33-
</span>
10+
<%= render(Blacklight::ConstraintLayoutComponent.new(
11+
classes: options[:classes],
12+
label: label,
13+
value: value,
14+
remove_path: options[:remove])) %>

lib/blacklight/search_state.rb

+22
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,22 @@ def to_hash
3737
end
3838
alias to_h to_hash
3939

40+
# Tiny shim to make it easier to migrate raw params access to using this class
41+
delegate :[], to: :params
42+
deprecation_deprecate :[]
43+
44+
def has_constraints?
45+
!(query_param.blank? && filter_params.blank?)
46+
end
47+
48+
def query_param
49+
params[:q]
50+
end
51+
52+
def filter_params
53+
params[:f] || {}
54+
end
55+
4056
def reset(params = nil)
4157
self.class.new(params || ActionController::Parameters.new, blacklight_config, controller)
4258
end
@@ -57,6 +73,12 @@ def url_for_document(doc, options = {})
5773
end
5874
end
5975

76+
def remove_query_params
77+
p = reset_search_params
78+
p.delete(:q)
79+
p
80+
end
81+
6082
# adds the value and/or field to params[:f]
6183
# Does NOT remove request keys and otherwise ensure that the hash
6284
# is suitable for a redirect. See

spec/views/catalog/_constraints_element.html.erb_spec.rb renamed to spec/components/blacklight/constraint_layout_component_spec.rb

+21-11
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,34 @@
11
# frozen_string_literal: true
22

3-
RSpec.describe "catalog/_constraints_element.html.erb" do
3+
require 'spec_helper'
4+
5+
RSpec.describe Blacklight::ConstraintLayoutComponent, type: :component do
6+
subject(:render) do
7+
render_inline(described_class.new(params))
8+
end
9+
10+
let(:rendered) do
11+
Capybara::Node::Simple.new(render)
12+
end
13+
414
describe "for simple display" do
5-
before do
6-
render partial: "catalog/constraints_element", locals: { label: "my label", value: "my value" }
15+
let(:params) do
16+
{ label: "my label", value: "my value" }
717
end
818

919
it "renders label and value" do
1020
expect(rendered).to have_selector("span.applied-filter.constraint") do |s|
1121
expect(s).to have_css("span.constraint-value")
1222
expect(s).not_to have_css("a.constraint-value")
13-
expect(s).to have_selector "span.filter-name", content: "my label"
14-
expect(s).to have_selector "span.filter-value", content: "my value"
23+
expect(s).to have_selector "span.filter-name", text: "my label"
24+
expect(s).to have_selector "span.filter-value", text: "my value"
1525
end
1626
end
1727
end
1828

1929
describe "with remove link" do
20-
before do
21-
render partial: "catalog/constraints_element", locals: { label: "my label", value: "my value", options: { remove: "http://remove" } }
30+
let(:params) do
31+
{ label: "my label", value: "my value", remove_path: "http://remove" }
2232
end
2333

2434
it "includes remove link" do
@@ -34,8 +44,8 @@
3444
end
3545

3646
describe "with custom classes" do
37-
before do
38-
render partial: "catalog/constraints_element", locals: { label: "my label", value: "my value", options: { classes: %w[class1 class2] } }
47+
let(:params) do
48+
{ label: "my label", value: "my value", classes: %w[class1 class2] }
3949
end
4050

4151
it "includes them" do
@@ -44,8 +54,8 @@
4454
end
4555

4656
describe "with no escaping" do
47-
before do
48-
render(partial: "catalog/constraints_element", locals: { label: "<span class='custom_label'>my label</span>".html_safe, value: "<span class='custom_value'>my value</span>".html_safe })
57+
let(:params) do
58+
{ label: "<span class='custom_label'>my label</span>".html_safe, value: "<span class='custom_value'>my value</span>".html_safe }
4959
end
5060

5161
it "does not escape key and value" do

spec/helpers/blacklight/render_constraints_helper_behavior_spec.rb

+4-23
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
allow(helper).to receive(:search_action_path) do |*args|
1414
search_catalog_path *args
1515
end
16+
17+
allow(helper).to receive(:blacklight_config).and_return(config)
18+
allow(controller).to receive(:search_state_class).and_return(Blacklight::SearchState)
1619
end
1720

1821
describe '#render_constraints_query' do
@@ -22,24 +25,7 @@
2225
let(:params) { ActionController::Parameters.new(q: 'foobar', f: { type: 'journal' }) }
2326

2427
it "has a link relative to the current url" do
25-
expect(subject).to have_selector "a[href='/?f%5Btype%5D=journal']"
26-
end
27-
28-
context 'with an ordinary hash' do
29-
let(:params) { { q: 'foobar', f: { type: 'journal' } } }
30-
31-
it "has a link relative to the current url" do
32-
expect(subject).to have_selector "a[href='/?f%5Btype%5D=journal']"
33-
end
34-
end
35-
36-
context "with a route_set" do
37-
let(:params) { ActionController::Parameters.new(q: 'foobar', f: { type: 'journal' }, route_set: my_engine) }
38-
39-
it "accepts an optional route set" do
40-
expect(my_engine).to receive(:url_for).and_return('/?f%5Btype%5D=journal')
41-
expect(subject).to have_selector "a[href='/?f%5Btype%5D=journal']"
42-
end
28+
expect(subject).to have_link 'Remove constraint', href: '/catalog?f%5Btype%5D=journal'
4329
end
4430
end
4531

@@ -73,11 +59,6 @@
7359

7460
let(:params) { ActionController::Parameters.new f: { 'type' => [''] } }
7561

76-
before do
77-
allow(helper).to receive(:blacklight_config).and_return(config)
78-
allow(controller).to receive(:search_state_class).and_return(Blacklight::SearchState)
79-
end
80-
8162
it "renders nothing for empty facet limit param" do
8263
expect(subject).to be_blank
8364
end

0 commit comments

Comments
 (0)