blacklight_advanced_search 2.2.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. data/Gemfile +8 -0
  2. data/{README.rdoc → README.md} +85 -59
  3. data/Rakefile +2 -2
  4. data/VERSION +1 -1
  5. data/app/assets/javascripts/blacklight_advanced_search.js +4 -4
  6. data/app/assets/stylesheets/blacklight_advanced_search/advanced_results.css +11 -31
  7. data/app/assets/stylesheets/blacklight_advanced_search/blacklight_advanced_search_styles.css.scss +42 -7
  8. data/app/controllers/blacklight_advanced_search/advanced_controller.rb +1 -3
  9. data/app/helpers/advanced_helper.rb +13 -9
  10. data/app/views/advanced/_advanced_search_facets.html.erb +15 -2
  11. data/app/views/advanced/_advanced_search_facets_as_select.html.erb +30 -0
  12. data/app/views/advanced/_advanced_search_fields.html.erb +5 -3
  13. data/app/views/advanced/_advanced_search_form.html.erb +26 -25
  14. data/app/views/advanced/_advanced_search_help.html.erb +19 -17
  15. data/app/views/advanced/_advanced_search_submit_btns.html.erb +12 -0
  16. data/app/views/advanced/_facet_limit.html.erb +11 -3
  17. data/app/views/advanced/index.html.erb +19 -6
  18. data/app/views/blacklight_advanced_search/_facet_limit.html.erb +8 -3
  19. data/blacklight_advanced_search.gemspec +7 -3
  20. data/config/locales/blacklight_advanced_search.en.yml +12 -0
  21. data/lib/blacklight_advanced_search.rb +28 -17
  22. data/lib/blacklight_advanced_search/advanced_query_parser.rb +26 -15
  23. data/lib/blacklight_advanced_search/redirect_legacy_params_filter.rb +32 -0
  24. data/lib/blacklight_advanced_search/render_constraints_override.rb +33 -7
  25. data/spec/features/blacklight_advanced_search_form_spec.rb +5 -5
  26. data/spec/lib/deep_merge_spec.rb +45 -0
  27. data/spec/test_app_templates/Gemfile.extra +2 -0
  28. data/spec/test_app_templates/lib/generators/test_app_generator.rb +1 -1
  29. metadata +41 -15
  30. data/app/assets/javascripts/blacklight_advanced_search/blacklight_advanced_search_javascript.js +0 -48
  31. data/app/views/advanced/_facet_layout.html.erb +0 -5
data/Gemfile CHANGED
@@ -2,6 +2,8 @@ source 'http://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
+ gem 'rails', '~> 4.0'
6
+
5
7
  group :test do
6
8
  gem "bootstrap-sass"
7
9
  gem 'turbolinks'
@@ -9,7 +11,13 @@ end
9
11
 
10
12
  gem 'activerecord-jdbcsqlite3-adapter', platform: :jruby
11
13
  gem 'sqlite3', platform: :ruby
14
+
15
+ # These need to be listed here explicitly for engine_cart testing to work,
16
+ # not really sure why the existing gemspec and Gemfile of test app aren't enough.
12
17
  gem 'jquery-rails'
18
+ gem 'blacklight_marc'
19
+ gem 'sass-rails'
20
+
13
21
 
14
22
  if File.exists?('spec/test_app_templates/Gemfile.extra')
15
23
  eval File.read('spec/test_app_templates/Gemfile.extra'), nil, 'spec/test_app_templates/Gemfile.extra'
@@ -1,13 +1,20 @@
1
1
  This is an advanced search plugin for Blacklight ( http://www.projectblacklight.org ).
2
2
 
3
- == Blacklight version compatibility
3
+ ## Blacklight version compatibility
4
4
 
5
- This is a plugin for Blacklight: http://github.com/projectblacklight/blacklight
5
+ This is a plugin for [Blacklight](http://github.com/projectblacklight/blacklight)
6
6
 
7
7
  It has been hard to keep track of which versions of `blacklight_advanced_search`
8
8
  work with which versions of `blacklight`. Some notes:
9
9
 
10
10
  * versions 5.x of Advanced Search plugin should work with Blacklight >= 5.1 and < 6 -- we now synchronize the _major_ version number between `blacklight` and `blacklight_advanced_search`.
11
+ * `blacklight_advanced_search` 5.x changes the URL query param format for advanced 'inclusive'
12
+ facet selections, from the advanced form. If you'd like to keep old-style possibly
13
+ bookmarked URLs working, by redirecting to new format, add this to your
14
+ `CatalogController`:
15
+
16
+ before_filter BlacklightAdvancedSearch::RedirectLegacyParamsFilter, :only => :index
17
+
11
18
  * version 2.2 of `blacklight_advanced_search` should work with `blacklight` 4.x.
12
19
  * versions `1.2.*` of Advanced Search plugin can work with blacklight 3.2.2 through latest 3.2.x
13
20
  * 1.2.0 was an aborted version, don't use it, if you did, re-do your configuration according to current instructions and delete any local ./app/controllers/advanced_controller.rb file.
@@ -15,46 +22,45 @@ work with which versions of `blacklight`. Some notes:
15
22
  * advanced search plugin latest 0.X.X version will work with Blacklight 2.9/Rails2.
16
23
  * Older tagged versions of Advanced Search may work with even older BL.
17
24
 
18
- == Installation:
25
+ ## Installation
19
26
 
20
- === Blacklight 3.x/Rails 3
27
+ ### Blacklight 3.x/Rails 3
21
28
 
22
29
  Add to your application's Gemfile:
23
30
 
24
- gem "blacklight_advanced_search"
31
+ gem "blacklight_advanced_search"
25
32
 
26
33
  then run 'bundle install'. Then run:
27
34
 
28
- rails generate blacklight_advanced_search
35
+ rails generate blacklight_advanced_search
29
36
 
30
37
  * The 'generate' command will install 'require' statements for the plugin's assets into your application's application.js/application.css asset pipeline files
31
38
  * And it can optionally install a localized search form with a link to advanced search. If you've already localized your search form you'll want to do this manually instead.
32
39
 
33
40
  You may want to `include BlacklightAdvancedSearch::ParseBasicQ` in your CatalogController to enable AND/OR/NOT parsing even in ordinary search, this is not on by default.
34
41
 
35
- == Accessing
42
+ ## Accessing
36
43
 
37
44
  The advanced search form will be available in your app at /advanced, and in your app using
38
45
  routing helper `advanced_search_path`.
39
46
 
40
- advanced_search_path
47
+ advanced_search_path
41
48
 
42
49
  You can also send the advanced search form url parameters representing a search, to have the form add on additional 'advanced' criteria to the search. For example:
43
50
 
44
- advanced_search_path( params )
51
+ advanced_search_path( params )
45
52
 
46
53
  By default there won't be any links in your application to the search form. If you've heavily customized your app, you can put them wherever you want as above.
47
54
 
48
55
  However, especially if your app isn't much customized, the optional installer can write a localized Blacklight search form into your application with a 'more options' link to advanced. You may need to adjust your styles to make room for the new link, depending on what you've done with your app.
49
56
 
50
57
 
58
+ ## Configuration
51
59
 
52
- == Configuration:
53
-
54
- If your application uses a single Solr qt request handler for all its search fields, then this plugin may work well with no configuration. Nonetheless, configuration is available to change or improve behavior, or to use a separate Solr request handler for the advanced search plugin. Most configuration takes place in your ./app/controllers/catalog_controller.rb `configure_blacklight` block.
60
+ If your application uses a single Solr qt request handler for all its search fields, then this plugin may work well with no configuration. Nonetheless, configuration is available to change or improve behavior, or to use a separate Solr request handler for the advanced search plugin. Most configuration takes place in your `./app/controllers/catalog_controller.rb` `configure_blacklight` block.
55
61
 
56
62
 
57
- === Expression parsing in ordinary search
63
+ ### Expression parsing in ordinary search
58
64
 
59
65
  Turn this feature on by adding to your CatalogController definition:
60
66
 
@@ -76,7 +82,7 @@ Due to limitations of the logic, sometimes these generated Solr queries may not
76
82
 
77
83
  If there'a a parse error trying to parse as boolean expression, it'll give up and pass the query on through same as it would without ParseBasicQ.
78
84
 
79
- === Search fields
85
+ ### Search fields
80
86
 
81
87
  Your main blacklight search fields are generally defined in CatalogController blacklight_config using `add_search_field`. They are all by default used in advanced search.
82
88
 
@@ -89,10 +95,10 @@ If there are particular search fields in your main blacklight config you want ex
89
95
 
90
96
  If you want search fields ONLY available in advanced search, you can suppress them from ordinary search:
91
97
 
92
- config.add_search_field("publisher") do |field|
98
+ config.add_search_field("publisher") do |field|
93
99
  field.include_in_simple_select = false
94
100
  field.solr_parameters = { :qf => "publisher_t" }
95
- end
101
+ end
96
102
 
97
103
  All advanced search fields must share the same Solr request handler (":qt"). As such, search fields that use a custom ":qt" parameter may not be re-used by the advanced search plugin. However, you may use a separate Solr request handler than the Blacklight default. If you would like the advanced search to use a different Solr request handler than your app's default, set:
98
104
 
@@ -115,30 +121,30 @@ Additionally, to make your advanced search solr requests more concise, you are s
115
121
 
116
122
  Within your solrconfig.xml you may then provide the appropriate custom configuration.
117
123
 
118
- <requestHandler name="advanced" class="solr.SearchHandler" >
119
- <lst name="defaults">
120
- <!-- ... -->
121
- <str name="qf_author">
122
- author_1xx_unstem_search^200
123
- author_7xx_unstem_search^50
124
- author_8xx_unstem_search^10
125
- author_1xx_search^20 vern_author_1xx_search^20
126
- author_7xx_search^5 vern_author_7xx_search^5
127
- author_8xx_search vern_author_8xx_search
128
- </str>
129
- <str name="pf_author">
130
- author_1xx_unstem_search^5000
131
- author_7xx_unstem_search^3000
132
- author_1xx_search^500 vern_author_1xx_search^500
133
- author_7xx_search^300 vern_author_7xx_search^300
134
- author_8xx_unstem_search^250
135
- author_8xx_search^200 vern_author_8xx_search^200
136
- </str>
137
- </lst>
138
- </requestHandler>
139
-
140
-
141
- === Facets
124
+ <requestHandler name="advanced" class="solr.SearchHandler" >
125
+ <lst name="defaults">
126
+ <!-- ... -->
127
+ <str name="qf_author">
128
+ author_1xx_unstem_search^200
129
+ author_7xx_unstem_search^50
130
+ author_8xx_unstem_search^10
131
+ author_1xx_search^20 vern_author_1xx_search^20
132
+ author_7xx_search^5 vern_author_7xx_search^5
133
+ author_8xx_search vern_author_8xx_search
134
+ </str>
135
+ <str name="pf_author">
136
+ author_1xx_unstem_search^5000
137
+ author_7xx_unstem_search^3000
138
+ author_1xx_search^500 vern_author_1xx_search^500
139
+ author_7xx_search^300 vern_author_7xx_search^300
140
+ author_8xx_unstem_search^250
141
+ author_8xx_search^200 vern_author_8xx_search^200
142
+ </str>
143
+ </lst>
144
+ </requestHandler>
145
+
146
+
147
+ ### Facets on advanced search form
142
148
 
143
149
  By default, the advanced search form will show as limits whatever facets are configured as default in your Solr request handler. To have the advanced search form request specific facets and/or specific facet parameters, you can set config[:form_solr_parameters].
144
150
 
@@ -149,42 +155,64 @@ By default, the advanced search form will show as limits whatever facets are con
149
155
  "facet.sort" => "index" # sort by byte order of values
150
156
  }
151
157
  }
152
-
153
158
 
154
- === Advanced Search Config Options
159
+ Multiply selected advanced search form facets are combined with `or` (ie `any` or `union`).
160
+
161
+ The default advanced search form facet display is very much like Blacklight's
162
+ sidebar facets (and uses some code straight from BL to render), but with checkboxes
163
+ next to each value.
164
+
165
+ (IN PROGRESS) An alternate view using a multi-element HTML `select` is available, and can also
166
+ be combined with [chosen.js](http://harvesthq.github.io/chosen/) for a fancy type-ahead style of UI.
167
+ This can be especially useful if you want to offer many facet values at once on
168
+ the form (beware, they are all still loaded in HTML, so this is probably good for
169
+ at most hundreds, not thousands.)
170
+
171
+ config.advanced_search = {
172
+ # ...
173
+ :form_facet_partial => "advanced_search_facets_as_select"
174
+ }
175
+
176
+ ### Advanced Search Config Options
155
177
 
156
178
  Complete list of keys that can be supplied inside your configure_blacklight `advanced_search` block:
157
179
 
158
- [:qt]
159
- Solr request handler to use for any search that includes advanced search criteria. Defaults to what the application has set as blacklight_config.default_solr_params[:qt]
160
- [:url_key]
161
- Key to use in application URLs to indicate advanced search is included in a query, defaults to "advanced". URLs will have "&search_field=[url key]".
162
- [:form_solr_paramters]
163
- A hash of solr parameters which will be included in Solr request sent before display of advanced search form. Can be used to set facet parameters for advanced search form display.
164
- [:query_parser]
165
- advanced searches are translated to solr nested queries, where the inner queries are of a dismax-type.
180
+ * :qt
181
+ * Solr request handler to use for any search that includes advanced search criteria. Defaults to what the application has set as blacklight_config.default_solr_params[:qt]
182
+ * :url_key
183
+ * Key to use in application URLs to indicate advanced search is included in a query, defaults to "advanced". URLs will have "&search_field=[url key]".
184
+ * :form_solr_paramters
185
+ * A hash of solr parameters which will be included in Solr request sent before display of advanced search form. Can be used to set facet parameters for advanced search form display.
186
+ * :query_parser
187
+ * advanced searches are translated to solr nested queries, where the inner queries are of a dismax-type.
166
188
  By default, they are actually specifically 'dismax', but you can set :query_parser to 'edismax' instead.
167
189
  This may make additional features available like * wildcards in advanced searches; but it may also
168
190
  cause some user query elements to be interpreted as operators for edismax when they
169
191
  were intended as literals. Somewhat experimental. See Github issues #11 and #14.
170
192
 
193
+ ## Customizing the advanced search form
194
+
195
+ Most of the labels on the advanced search form are [provided via Rails i18n](./config/locales), and can
196
+ be customized in a local app i18n file.
197
+
198
+ Additionally, you can override the templates from this gem used to display the form.
199
+ We've tried to break it up into partials at the right granularity for over-riding
200
+ in likely ways. For one example, see the wiki page on [Adding a range limit to the advanced search form](https://github.com/projectblacklight/blacklight_advanced_search/wiki/Adding-a-range-limit-to-the-advanced-search-form).
201
+
171
202
 
172
- == Translation to Solr Query, technical details
203
+ ## Translation to Solr Query, technical details
173
204
 
174
205
  The code for mapping a user-entered query to a Solr query is called "nesting_parsing", and maps to a 'lucene' query parser query, with nested 'dismax' query parser queries.
175
206
 
176
207
  Some technical details can be found in the nesting_parsing README: [https://github.com/projectblacklight/blacklight_advanced_search/tree/master/lib/parsing_nesting]
177
208
 
178
209
  You may also find the rspecs for parsing a user-entered query and converting it to Solr illumnating:
210
+
179
211
  1. Converting user-entered query to Solr: [https://github.com/projectblacklight/blacklight_advanced_search/blob/master/spec/parsing_nesting/to_solr_spec.rb]
180
212
  2. Parsing user-entered query to internal syntax tree: [https://github.com/projectblacklight/blacklight_advanced_search/blob/master/spec/parsing_nesting/build_tree_spec.rb]
181
213
 
182
- == Running tests
214
+ ## Running tests
183
215
 
184
- The Blacklight Advanced Search acceptance tests require a copy of the blacklight-jetty demo index. You can get a copy by running:
185
-
186
- git submodule init
187
- git submodule update
188
216
 
189
217
  (Limited) test coverage is provided with rspec, run all tests (and start the jetty instance) by running:
190
218
  rake ci
@@ -192,9 +220,7 @@ The Blacklight Advanced Search acceptance tests require a copy of the blacklight
192
220
  from the blacklight_advanced_search directory. Note: you may need to `bundle install` first.
193
221
 
194
222
 
195
- == To Do
223
+ ## To Do
196
224
 
197
225
  * Alphabetical sorting of facet values returned by solr in count order (perhaps with limit).
198
226
  * Parse for fielded search too like << title:"some title" >>. 'field:' that doesn't match an actual known field should be passed through same as now, while recognized fields should generate nested queries tied to those blacklight search types.
199
-
200
-
data/Rakefile CHANGED
@@ -13,7 +13,6 @@ require 'engine_cart/rake_task'
13
13
 
14
14
  require 'jettywrapper'
15
15
  require 'blacklight'
16
- import File.join(Blacklight.root, 'lib', 'railties', 'solr_marc.rake')
17
16
 
18
17
  task :default => :ci
19
18
 
@@ -25,7 +24,8 @@ end
25
24
  desc "Load fixtures"
26
25
  task :fixtures => ['engine_cart:generate'] do
27
26
  within_test_app do
28
- system "rake solr:marc:index_test_data RAILS_ENV=test"
27
+ ENV['RAILS_ENV'] ||= 'test'
28
+ system "rake blacklight:solr:seed"
29
29
  abort "Error running fixtures" unless $?.success?
30
30
  end
31
31
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.2.0
1
+ 5.0.0
@@ -1,5 +1,5 @@
1
- // Master manifest file for engine, so local app can require
2
- // this one file, but get all our files -- and local app
3
- // require does not need to change if we change file list.
1
+ // Yeah, this is empty right now. It used to have stuff.
2
+ // We're leaving it here, so if in future versions of advanced_search it has
3
+ // stuff, existing apps will already be linked in.
4
4
 
5
- //= require_tree './blacklight_advanced_search'
5
+ //Is this a bad idea, it should just be removed? Not sure.
@@ -2,40 +2,20 @@
2
2
 
3
3
  /* constraints */
4
4
 
5
+ .inclusive_or.appliedFilter {
6
+ /* kinda lame, but we have to group the 'any' criteria somehow, as they are still
7
+ 'and'd with facet and other criteria. It's got a bootstrap 'well' class
8
+ on it already. */
9
+ display: inline-block;
10
+ padding: 4px 8px;
11
+ margin: 0;
12
+ }
13
+
5
14
  .inclusive_or .operator {
6
15
  margin-right: 1em;
7
16
  }
8
17
 
9
- .inclusive_or .appliedFilter {
10
- background-color: #F0F0F0;
11
- }
12
18
 
13
- /* making it match an h3 */
14
19
  #appliedParams .inclusive_or .operator {
15
- font-weight: bold;
16
- color: #555555;
17
- font-size: 108%;
18
- }
19
-
20
- /* Facet limit */
21
-
22
- /* over-ride BL */
23
- #facets .advanced_facet_limit ul {
24
- border-bottom: none;
25
- padding-bottom: 0;
26
- }
27
-
28
-
29
- .facet_limit .inclusive_or h4 {
30
- margin-bottom: 0.5em;
31
- }
32
-
33
- .facet_limit .inclusive_or li {
34
- margin-left: 1em;
35
- }
36
-
37
- /* optional link to search form */
38
- .search .advanced_search {
39
- font-size: 83.33%;
40
- }
41
-
20
+ font-weight: 500;
21
+ }
@@ -1,10 +1,6 @@
1
1
 
2
2
  /* Random styles */
3
3
 
4
- form.advanced h4 select {
5
- height: auto;
6
- margin: 0;
7
- }
8
4
 
9
5
 
10
6
  form.advanced .adv_facet_selections {
@@ -14,10 +10,49 @@ form.advanced .adv_facet_selections {
14
10
  margin-top: 0.25em;
15
11
  }
16
12
 
13
+ .advanced-search-form {
14
+ .query-criteria-heading {
15
+ // seems neccesary to get select menu to align okay, not sure why.
16
+ vertical-align: bottom;
17
+ margin-top: 0;
18
+ }
19
+
20
+
21
+ select.form-control.sort-select {
22
+ width: auto; // why does Bootstrap try to insist on explicit width? dunno.
23
+ display: inline-block;
24
+ }
25
+
26
+ .query-criteria, .limit-criteria, .sort-submit-buttons {
27
+ margin-bottom: 4em;
28
+ }
17
29
 
18
- .advanced_help li {
19
- margin-top: 0.5em;
20
- margin-bottom: 0.5em;
21
30
  }
22
31
 
32
+ .blacklight-advanced-facet-select {
33
+ // have to do some terribly complicated things with display:table and NESTED
34
+ // tables to add our checkbox and <label> element and still use display-table
35
+ // to align everything. sorry!
36
+ .facet-checkbox, .label-and-count {
37
+ display: table-cell;
38
+ }
39
+
40
+ .label-and-count {
41
+ width: 100%;
42
+ padding-left: 1em;
43
+ }
44
+
45
+
46
+ label {
47
+ // a nested table, with existing from BL text and count as display:table-cell
48
+ // already. the "display:table-row" element is implicit and will be added
49
+ // by browser as a psuedo-element inside this label.
50
+ display:table;
51
+ width: 100%;
52
+ font-weight: normal;
53
+
54
+ margin: 0;
55
+ padding: 0;
56
+ }
57
+ }
23
58
 
@@ -19,9 +19,7 @@ class BlacklightAdvancedSearch::AdvancedController < CatalogController
19
19
  # that context -- but we dont' want to search within any
20
20
  # existing :q or ADVANCED facets, so we remove those params.
21
21
  adv_keys = blacklight_config.search_fields.keys.map {|k| k.to_sym}
22
- trimmed_params = params.reject do |k,v|
23
- adv_keys.include?(k.to_sym) # the individual q params
24
- end
22
+ trimmed_params = params.except *adv_keys
25
23
  trimmed_params.delete(:f_inclusive) # adv facets
26
24
 
27
25
  search_context_params = solr_search_params(trimmed_params)
@@ -17,20 +17,24 @@ module AdvancedHelper
17
17
 
18
18
  # Is facet value in adv facet search results?
19
19
  def facet_value_checked?(field, value)
20
- params[:f_inclusive] && params[:f_inclusive][field] && params[:f_inclusive][field][value]
20
+ BlacklightAdvancedSearch::QueryParser.new(params, blacklight_config).filters_include_value?(field, value)
21
+ end
22
+
23
+ def select_menu_for_field_operator
24
+ options = {
25
+ t('blacklight_advanced_search.all') => 'AND',
26
+ t('blacklight_advanced_search.any') => 'OR'
27
+ }.sort
28
+
29
+ return select_tag(:op, options_for_select(options,params[:op]), :class => 'input-small')
21
30
  end
22
31
 
23
32
  # Current params without fields that will be over-written by adv. search,
24
33
  # or other fields we don't want.
25
34
  def advanced_search_context
26
- my_params = params.dup
27
- [:page, :commit, :f_inclusive, :q, :search_field, :op, :action, :index, :sort, :controller].each do |bad_key|
28
- my_params.delete(bad_key)
29
- end
30
- search_fields_for_advanced_search.each do |key, field_def|
31
- my_params.delete( field_def[:key] )
32
- end
33
- my_params
35
+ my_params = params.except :page, :commit, :f_inclusive, :q, :search_field, :op, :action, :index, :sort, :controller, :utf8
36
+
37
+ my_params.except! *search_fields_for_advanced_search.map { |key, field_def| field_def[:key] }
34
38
  end
35
39
 
36
40
  def search_fields_for_advanced_search