diff --git a/app/components/blacklight_range_limit/range_form_component.rb b/app/components/blacklight_range_limit/range_form_component.rb index c2783947..de6eda24 100644 --- a/app/components/blacklight_range_limit/range_form_component.rb +++ b/app/components/blacklight_range_limit/range_form_component.rb @@ -10,11 +10,11 @@ def initialize(facet_field:, classes: BlacklightRangeLimit.classes) end def begin_value_default - @facet_field.selected_range.is_a?(Range) ? @facet_field.selected_range.first : @facet_field.min + @facet_field.selected_range.is_a?(Range) ? @facet_field.selected_range.begin : @facet_field.min end def end_value_default - @facet_field.selected_range.is_a?(Range) ? @facet_field.selected_range.last : @facet_field.max + @facet_field.selected_range.is_a?(Range) ? @facet_field.selected_range.end : @facet_field.max end def begin_input_name diff --git a/app/presenters/blacklight_range_limit/facet_item_presenter.rb b/app/presenters/blacklight_range_limit/facet_item_presenter.rb index b79f6025..79234f2d 100644 --- a/app/presenters/blacklight_range_limit/facet_item_presenter.rb +++ b/app/presenters/blacklight_range_limit/facet_item_presenter.rb @@ -15,15 +15,15 @@ def label_for_range view_context.t( range_limit_label_key, - begin: format_range_display_value(value.first), - begin_value: value.first, - end: format_range_display_value(value.last), - end_value: value.last + begin: format_range_display_value(value.begin), + begin_value: value.begin, + end: format_range_display_value(value.end), + end_value: value.end ) end def range_limit_label_key - if value.first == value.last + if value.begin == value.end 'blacklight.range_limit.single_html' else 'blacklight.range_limit.range_html' diff --git a/app/presenters/blacklight_range_limit/filter_field.rb b/app/presenters/blacklight_range_limit/filter_field.rb index 3cec6073..48f7c420 100644 --- a/app/presenters/blacklight_range_limit/filter_field.rb +++ b/app/presenters/blacklight_range_limit/filter_field.rb @@ -22,7 +22,7 @@ def add(item) if value.is_a? Range param_key = filters_key params[param_key] = (params[param_key] || {}).dup - params[param_key][config.key] = { begin: value.first, end: value.last } + params[param_key][config.key] = { begin: value.begin, end: value.end } new_state.reset(params) else super @@ -55,7 +55,7 @@ def values(except: []) elsif params.dig(param_key, config.key).is_a? Hash b_bound = params.dig(param_key, config.key, :begin).presence e_bound = params.dig(param_key, config.key, :end).presence - Range.new(b_bound&.to_i, e_bound&.to_i) if b_bound && e_bound + Range.new(b_bound&.to_i, e_bound&.to_i) if b_bound || e_bound end f = except.include?(:filters) ? [] : [range].compact diff --git a/lib/blacklight_range_limit/range_limit_builder.rb b/lib/blacklight_range_limit/range_limit_builder.rb index 1f4563b1..5c2b6f05 100644 --- a/lib/blacklight_range_limit/range_limit_builder.rb +++ b/lib/blacklight_range_limit/range_limit_builder.rb @@ -25,9 +25,17 @@ def add_range_limit_params(solr_params) next unless range_config[:chart_js] || range_config[:textual_facets] selected_value = search_state.filter(config.key).values.first - range = (selected_value if selected_value.is_a? Range) || range_config[:assumed_boundaries] - add_range_segments_to_solr!(solr_params, field_key, range.first, range.last) if range.present? + range = if selected_value.is_a? Range + selected_value + elsif range_config[:assumed_boundaries] + Range.new(*range_config[:assumed_boundaries]) + else + nil + end + + # If we have both ends of a range + add_range_segments_to_solr!(solr_params, field_key, range.begin, range.end) if range && range.count != Float::INFINITY end solr_params @@ -61,5 +69,34 @@ def fetch_specific_range_limit(solr_params) return solr_params end + # hacky polyfill for new Blacklight behavior we need, if we don't have it yet + # + # https://github.com/projectblacklight/blacklight/pull/3213 + # https://github.com/projectblacklight/blacklight/pull/3443 + bl_version = Gem.loaded_specs["blacklight"]&.version + if bl_version && (bl_version <= Gem::Version.new("8.6.1")) + def facet_value_to_fq_string(facet_field, value, use_local_params: true) + facet_config = blacklight_config.facet_fields[facet_field] + + # if it's an one-end range, and condition from original that would use query instead isn't met + if value.is_a?(Range) && (value.count == Float::INFINITY) && !facet_config&.query + # Adapted from + # https://github.com/projectblacklight/blacklight/blob/1494bd0884efe7a48623e9b37abe558fa6348e2a/lib/blacklight/solr/search_builder_behavior.rb#L362-L366 + + solr_field = facet_config.field if facet_config && !facet_config.query + solr_field ||= facet_field + + local_params = [] + local_params << "tag=#{facet_config.tag}" if use_local_params && facet_config && facet_config.tag + + prefix = "{!#{local_params.join(' ')}}" unless local_params.empty? + + "#{prefix}#{solr_field}:[#{value.begin || "*"} TO #{value.end || "*"}]" + else + super + end + end + end + end end diff --git a/spec/features/run_through_spec.rb b/spec/features/run_through_spec.rb index b02e9cfd..f42b7fa9 100644 --- a/spec/features/run_through_spec.rb +++ b/spec/features/run_through_spec.rb @@ -91,6 +91,50 @@ end end + context "open-ended range" do + it "can search" do + visit search_catalog_path + + click_button 'Publication Date Sort' + + within ".facet-limit.blacklight-pub_date_si" do + find("input#range_pub_date_si_begin").set("") + find("input#range_pub_date_si_end").set(end_range) + click_button "Apply limit" + end + + expect(page).to have_css(".applied-filter", text: /Publication Date Sort +to #{end_range}/) + expect(page).not_to have_text("No entries found") + expect(page).to have_css(".document") + + within ".facet-limit.blacklight-pub_date_si" do + # expect expandable limits + find("summary", text: "Range List").click + expect(page).to have_css("details ul.facet-values li") + end + end + end + + context "submitted with empty boundaries" do + it "does not apply filter" do + visit search_catalog_path + + click_button 'Publication Date Sort' + + within ".facet-limit.blacklight-pub_date_si" do + find("input#range_pub_date_si_begin").set("") + find("input#range_pub_date_si_end").set("") + click_button "Apply limit" + end + expect(page).not_to have_css(".applied-filter") + + click_button 'Publication Date Sort' + within ".facet-limit.blacklight-pub_date_si" do + expect(page).not_to have_css(".selected") + end + end + end + context 'when assumed boundaries configured' do before do CatalogController.blacklight_config.facet_fields['pub_date_si'].range_config = { diff --git a/spec/presenters/filter_field_spec.rb b/spec/presenters/filter_field_spec.rb index 8b8da739..c9e9bafc 100644 --- a/spec/presenters/filter_field_spec.rb +++ b/spec/presenters/filter_field_spec.rb @@ -19,9 +19,18 @@ describe '#add' do it 'adds a new range parameter' do new_state = filter.add(1999..2099) - expect(new_state.params.dig(:range, 'some_field')).to include begin: 1999, end: 2099 end + + it "adds end-less range" do + new_state = filter.add(1999..nil) + expect(new_state.params.dig(:range, 'some_field')).to include begin: 1999, end: nil + end + + it "adds begin-less range" do + new_state = filter.add(nil..2099) + expect(new_state.params.dig(:range, 'some_field')).to include begin: nil, end: 2099 + end end context 'with some existing data' do @@ -32,6 +41,12 @@ new_state = filter.add(1999..2099) expect(new_state.params.dig(:range, 'some_field')).to include begin: 1999, end: 2099 + + new_state = filter.add(1999..nil) + expect(new_state.params.dig(:range, 'some_field')).to include begin: 1999, end: nil + + new_state = filter.add(nil..2099) + expect(new_state.params.dig(:range, 'some_field')).to include begin: nil, end: 2099 end end @@ -66,6 +81,26 @@ end end + context 'with an end-less range' do + let(:param_values) { { range: { some_field: { begin: '2013', end: '' } } } } + + describe '#values' do + it 'converts the parameters to a Range' do + expect(filter.values).to eq [2013..nil] + end + end + end + + context 'with an begin-less range' do + let(:param_values) { { range: { some_field: { begin: '', end: '2022' } } } } + + describe '#values' do + it 'converts the parameters to a Range' do + expect(filter.values).to eq [nil..2022] + end + end + end + context 'with empty data' do let(:param_values) { { range: { some_field: { begin: '', end: '' } } } }