blacklight_range_limit 9.0.0.beta1 → 9.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +1 -1
- data/README.md +18 -12
- data/Rakefile +38 -0
- data/VERSION +1 -1
- data/app/components/blacklight_range_limit/range_facet_component.html.erb +4 -4
- data/app/components/blacklight_range_limit/range_facet_component.rb +12 -0
- data/app/components/blacklight_range_limit/range_form_component.html.erb +12 -2
- data/app/presenters/blacklight_range_limit/facet_item_presenter.rb +9 -0
- data/app/presenters/blacklight_range_limit/filter_field.rb +7 -1
- data/doc/example-screenshot.png +0 -0
- data/lib/blacklight_range_limit/controller_override.rb +7 -10
- data/lib/blacklight_range_limit/range_limit_builder.rb +28 -7
- data/lib/blacklight_range_limit.rb +4 -1
- data/lib/generators/blacklight_range_limit/install_generator.rb +4 -1
- data/package.json +1 -1
- data/spec/components/range_facet_component_spec.rb +61 -1
- data/spec/features/run_through_spec.rb +60 -7
- data/spec/requests/bad_param_requests_spec.rb +61 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bfe80b379721a4e19e01ecb97a0f1ca6335e2e85ae3914abec0f2ae9ee9546b6
|
4
|
+
data.tar.gz: cdc7468b2f1e7f649f72a9f4200948cbc543d9f1e6a86bcac03b467c65b18ba2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df819d6ceb0f782c612d1eb83648a178ed2f555b599df666240cfa2cc7a75d0b3554ff29ff12ada5bdf3766bb74be88b76d054a95fd233d41309d2737bcb6cf2
|
7
|
+
data.tar.gz: 269df83223ddbed2fa371c9b0aa1ebc6d5afff775d5a313a6482ba8948412456b59bbe7b1b438e51143fe2941c3e643b3ba98f5a918287ce32b4867542871c69
|
data/.github/workflows/ruby.yml
CHANGED
data/README.md
CHANGED
@@ -19,7 +19,7 @@ Decimal numbers and Dates are NOT supported; they theoretically could be in the
|
|
19
19
|
|
20
20
|
* Javascript requires you to be using either rails-importmaps or a package.json-based builder like jsbundling-rails or vite-ruby. Legacy "sprockets-only" is not supported, however propshaft or sprockets can be used as your base asset pipeline.
|
21
21
|
|
22
|
-
*
|
22
|
+
* Blacklight 7.0+. Rails 7.0+
|
23
23
|
|
24
24
|
|
25
25
|
# Installation
|
@@ -34,7 +34,10 @@ Run `rails generate blacklight_range_limit:install`
|
|
34
34
|
|
35
35
|
### Manual Javascript setup is not hard
|
36
36
|
|
37
|
-
The installer could have trouble figuring out how to add Javascript to your particular setup.
|
37
|
+
The installer could have trouble figuring out how to add Javascript to your particular setup. If it's not working right and you want the installer to skip asset generation, you can execute as `rails generate blacklight_range_limit:install --skip-assets`.
|
38
|
+
|
39
|
+
|
40
|
+
In the end, all you need is `blacklight-range-limit` either importmap-pinned (with its chart.js dependency), or added to your package.json, and then, in a file that has access to the `Blacklight` import:
|
38
41
|
|
39
42
|
import BlacklightRangeLimit from "blacklight-range-limit";
|
40
43
|
BlacklightRangeLimit.init({ onLoadHandler: Blacklight.onLoad });
|
@@ -59,7 +62,7 @@ For import map pins, note:
|
|
59
62
|
|
60
63
|
### Unreleased version?
|
61
64
|
|
62
|
-
If you'd like to use an
|
65
|
+
If you'd like to use an unreleased version from git, just add that to your Gemfile in the usual way.
|
63
66
|
|
64
67
|
importmap-rails use should then Just Work.
|
65
68
|
|
@@ -99,11 +102,11 @@ config.add_facet_field 'pub_date', label: 'Publication Year', range_config: {
|
|
99
102
|
chart_js: true,
|
100
103
|
textual_facets: true,
|
101
104
|
textual_facets_collapsible: true,
|
105
|
+
show_missing_link: true,
|
102
106
|
chart_segment_border_color: "rgba(0,0,0, 0.5)",
|
103
107
|
chart_segment_bg_color: "#ccddcc",
|
104
108
|
chart_aspect_ratio: "2"
|
105
|
-
|
106
|
-
)
|
109
|
+
}
|
107
110
|
```
|
108
111
|
|
109
112
|
* **:num_segments** :
|
@@ -112,19 +115,23 @@ config.add_facet_field 'pub_date', label: 'Publication Year', range_config: {
|
|
112
115
|
* Default null. For a result set that has not yet been limited, instead of taking boundaries from results and making a second AJAX request to fetch segments, just assume these given boundaries. If you'd like to avoid this second AJAX Solr call, you can set :assumed_boundaries to a two-element array of integers instead, and the assumed boundaries will always be used. Note this is live ruby code, you can put calculations in there like Time.now.year + 2.
|
113
116
|
* **chart_js**:
|
114
117
|
* Default true. If false, the Javascript chart is not loaded, you can still get textual facets for bucket with `textual_facets` config.
|
115
|
-
* **textual_facets**:
|
118
|
+
* **textual_facets**:
|
119
|
+
* Default true. Should we show textual facet list too? Universal design
|
116
120
|
for accessibility, may have accessibilty concerns to turn off.
|
117
|
-
* **textual_facets_collapsible**:
|
121
|
+
* **textual_facets_collapsible**:
|
122
|
+
* Put the textual facets in a collapse/expand
|
118
123
|
disclosure. If you set chart_js to false, may make sense to set this to false too, to have
|
119
124
|
textual facets only instead of chart?
|
120
|
-
* **
|
125
|
+
* **show_missing_link**:
|
126
|
+
* Default true. Display a link (with count) to results that are _missing_ a value for the range field.
|
127
|
+
* **chart_segment_border_color** / **chart_segment_bg_color**:
|
121
128
|
* Set colors for the edge and fill of the segment bars in the histogram.
|
122
|
-
* chart_aspect_ratio
|
123
|
-
|
129
|
+
* **chart_aspect_ratio**:
|
130
|
+
* Defaults to 2. For chart.js, will fill available width then this determines size of chart.
|
124
131
|
|
125
132
|
## Javascript dependencies
|
126
133
|
|
127
|
-
We use [chart.js](https://www.chartjs.org/) to draw the chart. It has one dependency of
|
134
|
+
We use [chart.js](https://www.chartjs.org/) to draw the chart. It has one dependency of its own. These need to be either pinned with importmap-rails, or used via the chart.js npm package and an npm-package-based bundler.
|
128
135
|
|
129
136
|
There is **no CSS** needed.
|
130
137
|
|
@@ -169,4 +176,3 @@ Once you are done iterating on your test you will need to stop the application s
|
|
169
176
|
# Publishing Javascript
|
170
177
|
|
171
178
|
run `npm publish` to push the javascript package to https://npmjs.org/package/blacklight-range-limit
|
172
|
-
|
data/Rakefile
CHANGED
@@ -25,6 +25,44 @@ task ci: ['engine_cart:generate'] do
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
+
desc "check npm and gem versions match before release"
|
29
|
+
task :guard_version_match do
|
30
|
+
gem_version = File.read(__dir__ + "/VERSION").chomp
|
31
|
+
npm_version = JSON.parse(File.read(__dir__ + "/package.json"))["version"]
|
32
|
+
|
33
|
+
# 9.0.0.beta1 in gem becomes 9.0.0-beta1 in npm
|
34
|
+
gem_version_parts = gem_version.split(".")
|
35
|
+
npm_version_required = [
|
36
|
+
gem_version_parts.slice(0, 3).join("."),
|
37
|
+
gem_version_parts.slice(3, gem_version_parts.length).join(".")
|
38
|
+
].join("-")
|
39
|
+
|
40
|
+
if npm_version != npm_version_required
|
41
|
+
raise <<~EOS
|
42
|
+
You should not publish without npm version in package.json matching gem version
|
43
|
+
|
44
|
+
gem version: #{gem_version}
|
45
|
+
package.json version: #{npm_version}
|
46
|
+
|
47
|
+
expected package.json version: #{npm_version_required}
|
48
|
+
|
49
|
+
EOS
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Get our guard to run before `rake release`'s, and warning afterwards
|
54
|
+
task "release:guard_clean" => :guard_version_match
|
55
|
+
Rake::Task["guard_version_match"].enhance do
|
56
|
+
puts <<~EOS
|
57
|
+
|
58
|
+
⚠️ Please remember to run `npm publish` the npm package too! ⚠️
|
59
|
+
|
60
|
+
If you don't have permission, please ask someone who does for help.
|
61
|
+
https://www.npmjs.com/package/blacklight-range-limit
|
62
|
+
|
63
|
+
EOS
|
64
|
+
end
|
65
|
+
|
28
66
|
|
29
67
|
namespace :test do
|
30
68
|
namespace :spec do
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
9.0.0.
|
1
|
+
9.0.0.beta2
|
@@ -19,7 +19,7 @@
|
|
19
19
|
<!-- no results profile if missing is selected -->
|
20
20
|
<% unless @facet_field.missing_selected? %>
|
21
21
|
<%# this has to be on page if you want calculated facets to show up, JS sniffs it.
|
22
|
-
it was very hard to get chart.js to be
|
22
|
+
it was very hard to get chart.js to be successfully responsive, required this wrapper!
|
23
23
|
https://github.com/chartjs/Chart.js/issues/11005 -%>
|
24
24
|
<div class="chart-wrapper mb-3" data-chart-wrapper="true" style="display: none; position: relative; width: 100%; aspect-ratio: <%= range_config[:chart_aspect_ratio] %>;">
|
25
25
|
</div>
|
@@ -30,18 +30,18 @@
|
|
30
30
|
(min = @facet_field.min) &&
|
31
31
|
(max = @facet_field.max) %>
|
32
32
|
<div class="distribution <%= 'chart_js' unless range_config[:chart_js] == false %>">
|
33
|
-
<!-- if
|
33
|
+
<!-- if we already fetched segments from solr, display them
|
34
34
|
here. Otherwise, display a link to fetch them, which JS
|
35
35
|
will AJAX fetch. -->
|
36
36
|
<% if @facet_field.range_queries.any? %>
|
37
37
|
<%= render BlacklightRangeLimit::RangeSegmentsComponent.new(facet_field: @facet_field) %>
|
38
38
|
<% else %>
|
39
|
-
<%= link_to(t('blacklight.range_limit.view_distribution'),
|
39
|
+
<%= link_to(t('blacklight.range_limit.view_distribution'), load_distribution_link, class: "load_distribution", "data-loading-message-html": t('blacklight.range_limit.loading_html')) %>
|
40
40
|
<% end %>
|
41
41
|
</div>
|
42
42
|
<% end %>
|
43
43
|
|
44
|
-
<% if @facet_field.missing_facet_item && !request.xhr? && uses_distribution? %>
|
44
|
+
<% if range_config[:show_missing_link] && @facet_field.missing_facet_item && !request.xhr? && uses_distribution? %>
|
45
45
|
<%= render BlacklightRangeLimit::RangeSegmentsComponent.new(facet_field: @facet_field, facet_items: [@facet_field.missing_facet_item], classes: ['missing', 'mt-3']) %>
|
46
46
|
<% end %>
|
47
47
|
<% end %>
|
@@ -31,5 +31,17 @@ module BlacklightRangeLimit
|
|
31
31
|
def uses_distribution?
|
32
32
|
range_config[:chart_js] || range_config[:textual_facets]
|
33
33
|
end
|
34
|
+
|
35
|
+
# URL that will return the distribution list of range seguments
|
36
|
+
def load_distribution_link
|
37
|
+
# For open-ended ranges, the selected range should take priority for the boundary
|
38
|
+
# over actual response min/max. Matters for multi-valued fields.
|
39
|
+
min = @facet_field.selected_range_facet_item&.value&.begin || @facet_field.min
|
40
|
+
max = @facet_field.selected_range_facet_item&.value&.end || @facet_field.max
|
41
|
+
|
42
|
+
return nil unless (min && max)
|
43
|
+
|
44
|
+
range_limit_url(range_start: min, range_end: max)
|
45
|
+
end
|
34
46
|
end
|
35
47
|
end
|
@@ -5,12 +5,22 @@
|
|
5
5
|
<div class="d-flex justify-content-between align-items-end">
|
6
6
|
<div class="d-flex flex-column mr-1 me-1">
|
7
7
|
<%= label_tag(begin_input_name, t("blacklight.range_limit.range_begin_short"), class: 'text-muted small mb-1') %>
|
8
|
-
<%= number_field_tag(begin_input_name,
|
8
|
+
<%= number_field_tag(begin_input_name,
|
9
|
+
begin_value_default,
|
10
|
+
min: range_config[:min_value],
|
11
|
+
max: range_config[:max_value],
|
12
|
+
class: "form-control form-control-sm range_begin")
|
13
|
+
%>
|
9
14
|
</div>
|
10
15
|
|
11
16
|
<div class="d-flex flex-column ml-1 ms-1">
|
12
17
|
<%= label_tag(end_input_name, t("blacklight.range_limit.range_end_short"), class: 'text-muted small mb-1') %>
|
13
|
-
<%= number_field_tag(end_input_name,
|
18
|
+
<%= number_field_tag(end_input_name,
|
19
|
+
end_value_default,
|
20
|
+
min: range_config[:min_value],
|
21
|
+
max: range_config[:max_value],
|
22
|
+
class: "form-control form-control-sm range_end")
|
23
|
+
%>
|
14
24
|
</div>
|
15
25
|
</div>
|
16
26
|
<div class="d-flex justify-content-end mt-2">
|
@@ -8,6 +8,15 @@ module BlacklightRangeLimit
|
|
8
8
|
label_for_range || super
|
9
9
|
end
|
10
10
|
|
11
|
+
# Very hacky way to keep params used for ajax query for segments out
|
12
|
+
# of our generated facet links. Sorry this seems to be the best way!
|
13
|
+
#
|
14
|
+
# https://github.com/projectblacklight/blacklight_range_limit/issues/296
|
15
|
+
def href(path_options = {})
|
16
|
+
override_to_nil = BlacklightRangeLimit::ControllerOverride::RANGE_LIMIT_FIELDS.collect { |f| [f, nil] }.to_h
|
17
|
+
super(path_options.merge(override_to_nil))
|
18
|
+
end
|
19
|
+
|
11
20
|
private
|
12
21
|
|
13
22
|
def label_for_range
|
@@ -50,7 +50,13 @@ module BlacklightRangeLimit
|
|
50
50
|
def values(except: [])
|
51
51
|
params = search_state.params
|
52
52
|
param_key = filters_key
|
53
|
-
range = if params.dig
|
53
|
+
range = if !params.try(:dig, param_key).respond_to?(:dig)
|
54
|
+
# bad data, not a hash at all, correct it. Yes, it's bad form to mutate
|
55
|
+
# params here, but we found no better solution -- this only necessary in BL
|
56
|
+
# prior to 8.x, not sure why, but this branch can be omitted in BL 8.
|
57
|
+
params.delete(param_key)
|
58
|
+
nil
|
59
|
+
elsif params.dig(param_key, config.key).is_a? Range
|
54
60
|
params.dig(param_key, config.key)
|
55
61
|
elsif params.dig(param_key, config.key).is_a? Hash
|
56
62
|
b_bound = params.dig(param_key, config.key, :begin).presence
|
data/doc/example-screenshot.png
CHANGED
Binary file
|
@@ -8,21 +8,18 @@ module BlacklightRangeLimit
|
|
8
8
|
|
9
9
|
RANGE_LIMIT_FIELDS = [:range_end, :range_field, :range_start].freeze
|
10
10
|
|
11
|
-
included do
|
12
|
-
before_action do
|
13
|
-
# Blacklight 7.25+: Allow range limit params if necessary
|
14
|
-
if blacklight_config.search_state_fields
|
15
|
-
missing_keys = RANGE_LIMIT_FIELDS - blacklight_config.search_state_fields
|
16
|
-
blacklight_config.search_state_fields.concat(missing_keys)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
11
|
# Action method of our own!
|
22
12
|
# Delivers a _partial_ that's a display of a single fields range facets.
|
23
13
|
# Used when we need a second Solr query to get range facets, after the
|
24
14
|
# first found min/max from result set.
|
25
15
|
def range_limit
|
16
|
+
# The builder in this action will need our special range_limit fields, so we
|
17
|
+
# must allow them.
|
18
|
+
if blacklight_config.search_state_fields
|
19
|
+
missing_keys = RANGE_LIMIT_FIELDS - blacklight_config.search_state_fields
|
20
|
+
blacklight_config.search_state_fields.concat(missing_keys)
|
21
|
+
end
|
22
|
+
|
26
23
|
@facet = blacklight_config.facet_fields[params[:range_field]]
|
27
24
|
raise ActionController::RoutingError, 'Not Found' unless @facet&.range
|
28
25
|
|
@@ -26,13 +26,7 @@ module BlacklightRangeLimit
|
|
26
26
|
|
27
27
|
selected_value = search_state.filter(config.key).values.first
|
28
28
|
|
29
|
-
range =
|
30
|
-
selected_value
|
31
|
-
elsif range_config[:assumed_boundaries]
|
32
|
-
Range.new(*range_config[:assumed_boundaries])
|
33
|
-
else
|
34
|
-
nil
|
35
|
-
end
|
29
|
+
range = bl_create_selected_range_value(selected_value, config)
|
36
30
|
|
37
31
|
# If we have both ends of a range
|
38
32
|
add_range_segments_to_solr!(solr_params, field_key, range.begin, range.end) if range && range.count != Float::INFINITY
|
@@ -98,5 +92,32 @@ module BlacklightRangeLimit
|
|
98
92
|
end
|
99
93
|
end
|
100
94
|
|
95
|
+
# @returns Range or nil
|
96
|
+
#
|
97
|
+
# Range created from a range value or from assumed boundaries if present, and clamped between min and max
|
98
|
+
def bl_create_selected_range_value(selected_value, field_config)
|
99
|
+
range_config = field_config.range_config
|
100
|
+
|
101
|
+
range = if selected_value.is_a? Range
|
102
|
+
selected_value
|
103
|
+
elsif range_config[:assumed_boundaries].is_a?(Range)
|
104
|
+
range_config[:assumed_boundaries]
|
105
|
+
elsif range_config[:assumed_boundaries] # Array of two things please
|
106
|
+
Range.new(*range_config[:assumed_boundaries])
|
107
|
+
else
|
108
|
+
nil
|
109
|
+
end
|
110
|
+
|
111
|
+
# clamp between config'd min and max
|
112
|
+
min = range_config[:min_value]
|
113
|
+
max = range_config[:max_value]
|
114
|
+
|
115
|
+
range = Range.new(
|
116
|
+
(range.begin.clamp(min, max) if range.begin),
|
117
|
+
(range.end.clamp(min, max) if range.end),
|
118
|
+
) if range
|
119
|
+
|
120
|
+
range
|
121
|
+
end
|
101
122
|
end
|
102
123
|
end
|
@@ -27,10 +27,13 @@ module BlacklightRangeLimit
|
|
27
27
|
chart_js: true,
|
28
28
|
textual_facets: true,
|
29
29
|
textual_facets_collapsible: true,
|
30
|
+
show_missing_link: true,
|
30
31
|
chart_segment_border_color: 'rgb(54, 162, 235)',
|
31
32
|
chart_segment_bg_color: 'rgba(54, 162, 235, 0.5)',
|
32
33
|
chart_aspect_ratio: 2,
|
33
|
-
assumed_boundaries: nil
|
34
|
+
assumed_boundaries: nil,
|
35
|
+
min_value: -2_147_483_648, # solr intfield min and max
|
36
|
+
max_value: 2_147_483_648
|
34
37
|
},
|
35
38
|
filter_class: BlacklightRangeLimit::FilterField,
|
36
39
|
presenter: BlacklightRangeLimit::FacetFieldPresenter,
|
@@ -4,10 +4,13 @@ module BlacklightRangeLimit
|
|
4
4
|
class InstallGenerator < Rails::Generators::Base
|
5
5
|
source_root File.expand_path('../templates', __FILE__)
|
6
6
|
|
7
|
+
class_option :'skip-assets', type: :boolean, default: false, desc: "Skip generation of assets into app"
|
7
8
|
class_option :'builder-path', type: :string, default: 'app/models/search_builder.rb', aliases: "-b", desc: "Set the path, relative to Rails root, to the Blacklight app's search builder class"
|
8
9
|
|
9
10
|
def generate_assets
|
10
|
-
|
11
|
+
unless options[:'skip-assets']
|
12
|
+
generate 'blacklight_range_limit:assets'
|
13
|
+
end
|
11
14
|
end
|
12
15
|
|
13
16
|
def install_catalog_controller_mixin
|
data/package.json
CHANGED
@@ -106,7 +106,67 @@ RSpec.describe BlacklightRangeLimit::RangeFacetComponent, type: :component do
|
|
106
106
|
it "renders a link to fetch distribution info" do
|
107
107
|
# need request_url for routing of links generated
|
108
108
|
with_request_url '/catalog' do
|
109
|
-
|
109
|
+
load_link = rendered.find(".distribution a.load_distribution[href]")
|
110
|
+
expect(load_link).to be_present
|
111
|
+
|
112
|
+
expect(load_link["href"]).to be_present
|
113
|
+
params = Rack::Utils.parse_nested_query(load_link["href"].split("?").try(:last))
|
114
|
+
expect(params["range_field"]).to eq facet_field.key
|
115
|
+
expect(params["range_start"]).to eq facet_field_params[:min].to_s
|
116
|
+
expect(params["range_end"]).to eq facet_field_params[:max].to_s
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'with open-ended query' do
|
122
|
+
let(:selected_max) { 200 }
|
123
|
+
let(:data_max) { 300 }
|
124
|
+
|
125
|
+
let(:facet_field) do
|
126
|
+
instance_double(
|
127
|
+
BlacklightRangeLimit::FacetFieldPresenter,
|
128
|
+
key: 'key',
|
129
|
+
active?: false,
|
130
|
+
collapsed?: false,
|
131
|
+
in_modal?: false,
|
132
|
+
label: 'My facet field',
|
133
|
+
selected_range: nil,
|
134
|
+
selected_range_facet_item: Blacklight::Solr::Response::Facets::FacetItem.new(..selected_max),
|
135
|
+
missing_facet_item: nil,
|
136
|
+
missing_selected?: false,
|
137
|
+
min: nil,
|
138
|
+
max: nil,
|
139
|
+
search_state: Blacklight::SearchState.new({}, nil),
|
140
|
+
range_config: BlacklightRangeLimit.default_range_config[:range_config],
|
141
|
+
modal_path: nil,
|
142
|
+
facet_field: facet_config,
|
143
|
+
**facet_field_params,
|
144
|
+
**extra_facet_field_params
|
145
|
+
)
|
146
|
+
end
|
147
|
+
|
148
|
+
let(:facet_field_params) do
|
149
|
+
{
|
150
|
+
range_queries: [],
|
151
|
+
min: 100,
|
152
|
+
max: data_max
|
153
|
+
}
|
154
|
+
end
|
155
|
+
|
156
|
+
# This can be relevant in multi-valued queries, where even though you limited to
|
157
|
+
# < 200, some items in search can ALSO have additional values greater than 200, but
|
158
|
+
# we don't want to include them in our range buckets.
|
159
|
+
it "renders fetch distribution with expressed boundaries taking priority" do
|
160
|
+
# need request_url for routing of links generated
|
161
|
+
with_request_url '/catalog' do
|
162
|
+
load_link = rendered.find(".distribution a.load_distribution[href]")
|
163
|
+
expect(load_link).to be_present
|
164
|
+
|
165
|
+
expect(load_link["href"]).to be_present
|
166
|
+
params = Rack::Utils.parse_nested_query(load_link["href"].split("?").try(:last))
|
167
|
+
expect(params["range_field"]).to eq facet_field.key
|
168
|
+
expect(params["range_start"]).to eq facet_field_params[:min].to_s
|
169
|
+
expect(params["range_end"]).to eq selected_max.to_s
|
110
170
|
end
|
111
171
|
end
|
112
172
|
end
|
@@ -136,14 +136,15 @@ describe 'Run through with javascript', js: true do
|
|
136
136
|
end
|
137
137
|
|
138
138
|
context 'when assumed boundaries configured' do
|
139
|
-
|
140
|
-
CatalogController.blacklight_config.facet_fields['pub_date_si'].range_config
|
141
|
-
|
142
|
-
|
143
|
-
|
139
|
+
around do |example|
|
140
|
+
original = CatalogController.blacklight_config.facet_fields['pub_date_si'].range_config
|
141
|
+
CatalogController.blacklight_config.facet_fields['pub_date_si'].range_config = original.merge({
|
142
|
+
:assumed_boundaries=>1900...2100,
|
143
|
+
})
|
144
|
+
|
145
|
+
example.run
|
144
146
|
|
145
|
-
|
146
|
-
CatalogController.blacklight_config.facet_fields['pub_date_si'].range_config = {}
|
147
|
+
CatalogController.blacklight_config.facet_fields['pub_date_si'].range_config = original
|
147
148
|
end
|
148
149
|
|
149
150
|
it 'should show the range limit with set boundaries' do
|
@@ -154,4 +155,56 @@ describe 'Run through with javascript', js: true do
|
|
154
155
|
expect(find("input#range_pub_date_si_end").value).to be_present
|
155
156
|
end
|
156
157
|
end
|
158
|
+
|
159
|
+
context 'when missing facet item is configured not to show' do
|
160
|
+
around do |example|
|
161
|
+
original = CatalogController.blacklight_config.facet_fields['pub_date_si'].range_config
|
162
|
+
CatalogController.blacklight_config.facet_fields['pub_date_si'].range_config = original.merge({
|
163
|
+
show_missing_link: false
|
164
|
+
})
|
165
|
+
|
166
|
+
example.run
|
167
|
+
|
168
|
+
CatalogController.blacklight_config.facet_fields['pub_date_si'].range_config = original
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'should not show the missing facet item' do
|
172
|
+
visit search_catalog_path
|
173
|
+
|
174
|
+
within ".facet-limit.blacklight-pub_date_si" do
|
175
|
+
expect(page).not_to have_css("ul.missing")
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
context "Range Limit text facets" do
|
181
|
+
# Make sure it works with strict permitted params
|
182
|
+
around do |example|
|
183
|
+
original = ActionController::Parameters.action_on_unpermitted_parameters
|
184
|
+
ActionController::Parameters.action_on_unpermitted_parameters = :raise
|
185
|
+
|
186
|
+
example.run
|
187
|
+
|
188
|
+
ActionController::Parameters.action_on_unpermitted_parameters = original
|
189
|
+
end
|
190
|
+
|
191
|
+
it "work with strict permitted params" do
|
192
|
+
visit search_catalog_path
|
193
|
+
|
194
|
+
click_button 'Publication Date Sort'
|
195
|
+
|
196
|
+
from_val, to_val = nil, nil
|
197
|
+
within ".facet-limit.blacklight-pub_date_si" do
|
198
|
+
find("summary", text: "Range List").click
|
199
|
+
|
200
|
+
facet_link = first(".facet-values li a")
|
201
|
+
from_val = facet_link.find("span[data-blrl-begin]")["data-blrl-begin"]
|
202
|
+
to_val = facet_link.find("span[data-blrl-end]")["data-blrl-end"]
|
203
|
+
|
204
|
+
facet_link.click
|
205
|
+
end
|
206
|
+
|
207
|
+
expect(page).to have_css(".applied-filter", text: /Publication Date Sort.*#{from_val} to #{to_val}/)
|
208
|
+
end
|
209
|
+
end
|
157
210
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CatalogController, type: :request do
|
4
|
+
let(:range_facet_field) { "pub_date_si" }
|
5
|
+
|
6
|
+
let(:parsed_body) { Nokogiri::HTML(response.body) }
|
7
|
+
|
8
|
+
describe "bad params should not produce uncaught exception when" do
|
9
|
+
it "bad root range" do
|
10
|
+
get "/catalog?range=bad"
|
11
|
+
|
12
|
+
expect(response.code).to eq("200")
|
13
|
+
expect(parsed_body.css("span.applied-filter")).not_to be_present
|
14
|
+
end
|
15
|
+
|
16
|
+
it "facet params are ill structured" do
|
17
|
+
get "/catalog?#{ {"f" => { range_facet_field => [{"=Library&q="=>""}] } }.to_param }"
|
18
|
+
|
19
|
+
expect(response.code).to eq("200")
|
20
|
+
expect(parsed_body.css("span.applied-filter")).not_to be_present
|
21
|
+
end
|
22
|
+
|
23
|
+
it "newline in range facet does not interupt facet" do
|
24
|
+
get "/catalog?#{ {"range"=>{ range_facet_field => {"begin"=>"1588\n", "end"=>"2020\n"}}}.to_param }"
|
25
|
+
|
26
|
+
expect(response.code).to eq("200")
|
27
|
+
expect(parsed_body.css("span.applied-filter")).to be_present
|
28
|
+
expect(parsed_body.css("span.applied-filter").collect(&:text)).to include(/1588.*to.*2020/)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "weird attack in range value is ignored" do
|
32
|
+
param_hash = {"range"=>{"year_facet_isim"=>{"begin"=>"1989',(;))#- --", "end"=>"1989',(;))#- --"}}}
|
33
|
+
get "/catalog?#{ param_hash.to_param }"
|
34
|
+
|
35
|
+
expect(response.code).to eq("200")
|
36
|
+
expect(parsed_body.css("span.applied-filter")).not_to be_present
|
37
|
+
end
|
38
|
+
|
39
|
+
it "empty range param is ignored" do
|
40
|
+
get "/catalog?#{ { "range" => { "year_facet_isim" => nil } }.to_param }"
|
41
|
+
|
42
|
+
expect(response.code).to eq("200")
|
43
|
+
expect(parsed_body.css("span.applied-filter")).not_to be_present
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "out of bounds range config" do
|
47
|
+
let(:max) { BlacklightRangeLimit.default_range_config[:range_config][:max_value] }
|
48
|
+
let(:min) { BlacklightRangeLimit.default_range_config[:range_config][:min_value] }
|
49
|
+
|
50
|
+
let(:too_high) { max.abs * 2 }
|
51
|
+
let(:too_low) { min.abs * -2 }
|
52
|
+
|
53
|
+
it "does not error" do
|
54
|
+
get "/catalog?#{ {"range"=>{ range_facet_field => {"begin"=> too_low, "end"=> too_high }}}.to_param }"
|
55
|
+
|
56
|
+
expect(response.code).to eq("200")
|
57
|
+
expect(parsed_body.css("span.applied-filter")).to be_present
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blacklight_range_limit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 9.0.0.
|
4
|
+
version: 9.0.0.beta2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Rochkind
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2024-
|
12
|
+
date: 2024-12-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: blacklight
|
@@ -258,6 +258,7 @@ files:
|
|
258
258
|
- spec/presenters/facet_field_presenter_spec.rb
|
259
259
|
- spec/presenters/facet_item_presenter_spec.rb
|
260
260
|
- spec/presenters/filter_field_spec.rb
|
261
|
+
- spec/requests/bad_param_requests_spec.rb
|
261
262
|
- spec/spec_helper.rb
|
262
263
|
- spec/support/presenter_test_helpers.rb
|
263
264
|
- spec/test_app_templates/Gemfile.extra
|
@@ -297,6 +298,7 @@ test_files:
|
|
297
298
|
- spec/presenters/facet_field_presenter_spec.rb
|
298
299
|
- spec/presenters/facet_item_presenter_spec.rb
|
299
300
|
- spec/presenters/filter_field_spec.rb
|
301
|
+
- spec/requests/bad_param_requests_spec.rb
|
300
302
|
- spec/spec_helper.rb
|
301
303
|
- spec/support/presenter_test_helpers.rb
|
302
304
|
- spec/test_app_templates/Gemfile.extra
|