blacklight 7.20.1 → 7.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.babelrc +11 -0
- data/.github/workflows/ruby.yml +2 -2
- data/Gemfile +1 -1
- data/README.md +1 -1
- data/VERSION +1 -1
- data/app/assets/javascripts/blacklight/blacklight.js +41 -28
- data/app/assets/stylesheets/blacklight/_constraints.scss +1 -1
- data/app/assets/stylesheets/blacklight/_controls.scss +2 -1
- data/app/components/blacklight/constraints_component.rb +2 -6
- data/app/components/blacklight/system/modal_component.html.erb +2 -2
- data/app/controllers/concerns/blacklight/catalog.rb +2 -2
- data/app/javascript/blacklight/core.js +5 -1
- data/app/javascript/blacklight/modal.js +1 -1
- data/app/models/concerns/blacklight/document/email.rb +18 -6
- data/app/models/concerns/blacklight/document/sms.rb +16 -4
- data/app/models/record_mailer.rb +9 -1
- data/app/presenters/blacklight/facet_item_presenter.rb +2 -0
- data/app/views/record_mailer/sms_record.text.erb +1 -1
- data/config/locales/blacklight.de.yml +1 -1
- data/lib/blacklight/configuration.rb +9 -0
- data/lib/blacklight/engine.rb +2 -0
- data/lib/blacklight/search_state/filter_field.rb +34 -19
- data/lib/blacklight/solr/response/facets.rb +2 -1
- data/lib/blacklight/solr/search_builder_behavior.rb +2 -14
- data/package.json +3 -1
- data/spec/controllers/catalog_controller_spec.rb +14 -2
- data/spec/features/axe_spec.rb +6 -7
- data/spec/features/facet_missing_spec.rb +12 -4
- data/spec/lib/blacklight/search_state/filter_field_spec.rb +3 -17
- data/spec/models/blacklight/configuration_spec.rb +92 -0
- data/spec/models/blacklight/document/email_spec.rb +32 -0
- data/spec/models/blacklight/document/sms_spec.rb +33 -0
- data/spec/models/blacklight/solr/response/facets_spec.rb +1 -1
- data/spec/models/blacklight/solr/search_builder_spec.rb +0 -13
- data/spec/models/record_mailer_spec.rb +30 -2
- data/spec/spec_helper.rb +3 -3
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f9ecb2c98805e0783286a52510875f35da4b19983fa3c9f174fcce921d2b630
|
4
|
+
data.tar.gz: 221bbc331cace14c9212c4be38d372b3a62b15fa5d16af116f79e90c53a5dafe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ebee61b6584dbf10836b754f3f390acc24dce35da380caf633986bd1792991aaec3c07b9299f0f32beed54e339eaec4e0051f2350c08b2111e855688665bf4d4
|
7
|
+
data.tar.gz: 251aca6a6d0908be8a3b75312bd1604e88b4a55810f3553b6634f281ecd79b176ac2ef04797e3a02f42f41c8eaec0d49d734f10a699f8a739c17a65a5cf515ca
|
data/.babelrc
ADDED
data/.github/workflows/ruby.yml
CHANGED
data/Gemfile
CHANGED
@@ -27,7 +27,7 @@ else
|
|
27
27
|
if ENV['RAILS_VERSION']
|
28
28
|
if ENV['RAILS_VERSION'] == 'edge'
|
29
29
|
gem 'rails', github: 'rails/rails'
|
30
|
-
ENV['ENGINE_CART_RAILS_OPTIONS'] = '--edge
|
30
|
+
ENV['ENGINE_CART_RAILS_OPTIONS'] = '--edge'
|
31
31
|
else
|
32
32
|
gem 'rails', ENV['RAILS_VERSION']
|
33
33
|
end
|
data/README.md
CHANGED
@@ -39,7 +39,7 @@ rails generate blacklight:install
|
|
39
39
|
|
40
40
|
## Contributing Code
|
41
41
|
|
42
|
-
Code contributions are always welcome, instructions for contributing can be found at [CONTRIBUTING.md](https://github.com/projectblacklight/blacklight/blob/
|
42
|
+
Code contributions are always welcome, instructions for contributing can be found at [CONTRIBUTING.md](https://github.com/projectblacklight/blacklight/blob/main/CONTRIBUTING.md).
|
43
43
|
|
44
44
|
## Configuring Apache Solr
|
45
45
|
You'll also want some information about how Blacklight expects [Apache Solr](http://lucene.apache.org/solr ) to run, which you can find in [README_SOLR](https://github.com/projectblacklight/blacklight/wiki/README_SOLR)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
7.
|
1
|
+
7.21.0
|
@@ -1,18 +1,22 @@
|
|
1
|
+
"use strict";
|
2
|
+
|
1
3
|
Blacklight = function () {
|
2
4
|
var buffer = new Array();
|
3
5
|
return {
|
4
|
-
onLoad: function (func) {
|
6
|
+
onLoad: function onLoad(func) {
|
5
7
|
buffer.push(func);
|
6
8
|
},
|
7
|
-
activate: function () {
|
9
|
+
activate: function activate() {
|
8
10
|
for (var i = 0; i < buffer.length; i++) {
|
9
11
|
buffer[i].call();
|
10
12
|
}
|
11
13
|
},
|
12
|
-
listeners: function () {
|
14
|
+
listeners: function listeners() {
|
13
15
|
var listeners = [];
|
14
16
|
|
15
|
-
if (typeof
|
17
|
+
if (typeof Turbo !== 'undefined') {
|
18
|
+
listeners.push('turbo:load');
|
19
|
+
} else if (typeof Turbolinks !== 'undefined' && Turbolinks.supported) {
|
16
20
|
// Turbolinks 5
|
17
21
|
if (Turbolinks.BrowserAdapter) {
|
18
22
|
listeners.push('turbolinks:load');
|
@@ -37,7 +41,9 @@ Blacklight.listeners().forEach(function (listener) {
|
|
37
41
|
});
|
38
42
|
});
|
39
43
|
Blacklight.onLoad(function () {
|
40
|
-
|
44
|
+
var elem = document.querySelector('.no-js'); // The "no-js" class may already have been removed because this function is
|
45
|
+
// run on every turbo:load event, in that case, it won't find an element.
|
46
|
+
|
41
47
|
if (!elem) return;
|
42
48
|
elem.classList.remove('no-js');
|
43
49
|
elem.classList.add('js');
|
@@ -87,7 +93,7 @@ Blacklight.onLoad(function () {
|
|
87
93
|
$(Blacklight.doBookmarkToggleBehavior.selector).blCheckboxSubmit({
|
88
94
|
// cssClass is added to elements added, plus used for id base
|
89
95
|
cssClass: 'toggle-bookmark',
|
90
|
-
success: function (checked, response) {
|
96
|
+
success: function success(checked, response) {
|
91
97
|
if (response.bookmarks) {
|
92
98
|
$('[data-role=bookmark-counter]').text(response.bookmarks.count);
|
93
99
|
}
|
@@ -105,8 +111,8 @@ Blacklight.onLoad(function () {
|
|
105
111
|
// Button clicks should change focus. As of 10/3/19, Firefox for Mac and
|
106
112
|
// Safari both do not set focus to a button on button click.
|
107
113
|
// See https://zellwk.com/blog/inconsistent-button-behavior/ for background information
|
108
|
-
document.querySelectorAll('button.collapse-toggle').forEach(button
|
109
|
-
button.addEventListener('click', ()
|
114
|
+
document.querySelectorAll('button.collapse-toggle').forEach(function (button) {
|
115
|
+
button.addEventListener('click', function () {
|
110
116
|
event.target.focus();
|
111
117
|
});
|
112
118
|
});
|
@@ -193,12 +199,12 @@ Blacklight.onLoad(function () {
|
|
193
199
|
dataType: 'json',
|
194
200
|
type: form.attr('method').toUpperCase(),
|
195
201
|
data: form.serialize(),
|
196
|
-
error: function () {
|
202
|
+
error: function error() {
|
197
203
|
label.removeAttr('disabled');
|
198
204
|
checkbox.removeAttr('disabled');
|
199
205
|
options.error.call();
|
200
206
|
},
|
201
|
-
success: function (data, status, xhr) {
|
207
|
+
success: function success(data, status, xhr) {
|
202
208
|
//if app isn't running at all, xhr annoyingly
|
203
209
|
//reports success with status 0.
|
204
210
|
if (xhr.status != 0) {
|
@@ -224,10 +230,10 @@ Blacklight.onLoad(function () {
|
|
224
230
|
$.fn.blCheckboxSubmit.defaults = {
|
225
231
|
//cssClass is added to elements added, plus used for id base
|
226
232
|
cssClass: 'blCheckboxSubmit',
|
227
|
-
error: function () {
|
233
|
+
error: function error() {
|
228
234
|
alert("Error");
|
229
235
|
},
|
230
|
-
success: function () {} //callback
|
236
|
+
success: function success() {} //callback
|
231
237
|
|
232
238
|
};
|
233
239
|
})(jQuery);
|
@@ -243,12 +249,12 @@ Blacklight.doResizeFacetLabelsAndCounts = function () {
|
|
243
249
|
}
|
244
250
|
|
245
251
|
document.querySelectorAll('.facet-values, .pivot-facet').forEach(function (elem) {
|
246
|
-
|
252
|
+
var nodes = elem.querySelectorAll('.facet-count'); // TODO: when we drop ie11 support, this can become the spread operator:
|
247
253
|
|
248
|
-
|
254
|
+
var longest = Array.from(nodes).sort(longer)[0];
|
249
255
|
|
250
256
|
if (longest && longest.textContent) {
|
251
|
-
|
257
|
+
var width = longest.textContent.length + 1 + 'ch';
|
252
258
|
elem.querySelector('.facet-count').style.width = width;
|
253
259
|
}
|
254
260
|
});
|
@@ -365,7 +371,7 @@ Blacklight.modal.onFailure = function (jqXHR, textStatus, errorThrown) {
|
|
365
371
|
Blacklight.modal.receiveAjax = function (contents) {
|
366
372
|
// does it have a data- selector for container?
|
367
373
|
// important we don't execute script tags, we shouldn't.
|
368
|
-
// code modelled off of JQuery ajax.load. https://github.com/jquery/jquery/blob/
|
374
|
+
// code modelled off of JQuery ajax.load. https://github.com/jquery/jquery/blob/main/src/ajax/load.js?source=c#L62
|
369
375
|
var container = $('<div>').append(jQuery.parseHTML(contents)).find(Blacklight.modal.containerSelector).first();
|
370
376
|
|
371
377
|
if (container.length !== 0) {
|
@@ -443,9 +449,9 @@ Blacklight.doSearchContextBehavior = function () {
|
|
443
449
|
return Blacklight.do_search_context_behavior();
|
444
450
|
}
|
445
451
|
|
446
|
-
|
452
|
+
var elements = document.querySelectorAll('a[data-context-href]'); // Equivalent to Array.from(), but supports ie11
|
447
453
|
|
448
|
-
|
454
|
+
var nodes = Array.prototype.slice.call(elements);
|
449
455
|
nodes.forEach(function (element) {
|
450
456
|
element.addEventListener('click', function (e) {
|
451
457
|
Blacklight.handleSearchContextMethod.call(e.currentTarget, e);
|
@@ -453,9 +459,17 @@ Blacklight.doSearchContextBehavior = function () {
|
|
453
459
|
});
|
454
460
|
};
|
455
461
|
|
456
|
-
Blacklight.csrfToken = ()
|
462
|
+
Blacklight.csrfToken = function () {
|
463
|
+
var _document$querySelect;
|
464
|
+
|
465
|
+
return (_document$querySelect = document.querySelector('meta[name=csrf-token]')) === null || _document$querySelect === void 0 ? void 0 : _document$querySelect.content;
|
466
|
+
};
|
467
|
+
|
468
|
+
Blacklight.csrfParam = function () {
|
469
|
+
var _document$querySelect2;
|
457
470
|
|
458
|
-
|
471
|
+
return (_document$querySelect2 = document.querySelector('meta[name=csrf-param]')) === null || _document$querySelect2 === void 0 ? void 0 : _document$querySelect2.content;
|
472
|
+
}; // this is the Rails.handleMethod with a couple adjustments, described inline:
|
459
473
|
// first, we're attaching this directly to the event handler, so we can check for meta-keys
|
460
474
|
|
461
475
|
|
@@ -467,22 +481,21 @@ Blacklight.handleSearchContextMethod = function (event) {
|
|
467
481
|
|
468
482
|
var link = this; // instead of using the normal href, we need to use the context href instead
|
469
483
|
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
484
|
+
var href = link.getAttribute('data-context-href');
|
485
|
+
var target = link.getAttribute('target');
|
486
|
+
var csrfToken = Blacklight.csrfToken();
|
487
|
+
var csrfParam = Blacklight.csrfParam();
|
488
|
+
var form = document.createElement('form');
|
475
489
|
form.method = 'post';
|
476
490
|
form.action = href;
|
477
|
-
|
478
|
-
<input name="redirect" value="${link.getAttribute('href')}" type="hidden" />`; // check for meta keys.. if set, we should open in a new tab
|
491
|
+
var formContent = "<input name=\"_method\" value=\"post\" type=\"hidden\" />\n <input name=\"redirect\" value=\"".concat(link.getAttribute('href'), "\" type=\"hidden\" />"); // check for meta keys.. if set, we should open in a new tab
|
479
492
|
|
480
493
|
if (event.metaKey || event.ctrlKey) {
|
481
494
|
target = '_blank';
|
482
495
|
}
|
483
496
|
|
484
497
|
if (csrfParam !== undefined && csrfToken !== undefined) {
|
485
|
-
formContent +=
|
498
|
+
formContent += "<input name=\"".concat(csrfParam, "\" value=\"").concat(csrfToken, "\" type=\"hidden\" />");
|
486
499
|
} // Must trigger submit by click on a button, else "submit" event handler won't work!
|
487
500
|
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit
|
488
501
|
|
@@ -63,14 +63,10 @@ module Blacklight
|
|
63
63
|
|
64
64
|
Deprecation.silence(Blacklight::SearchState) do
|
65
65
|
@search_state.filters.map do |facet|
|
66
|
-
missing_facet = @search_state.params.dig("f", "-#{facet.key}:").present?
|
67
66
|
facet.values.map do |val|
|
68
|
-
next if val.blank?
|
67
|
+
next if val.blank?
|
69
68
|
|
70
|
-
if
|
71
|
-
missing = I18n.t("blacklight.search.facets.missing")
|
72
|
-
yield facet_item_presenter(facet.config, missing, facet.key)
|
73
|
-
elsif val.is_a?(Array)
|
69
|
+
if val.is_a?(Array)
|
74
70
|
yield inclusive_facet_item_presenter(facet.config, val, facet.key) if val.any?(&:present?)
|
75
71
|
else
|
76
72
|
yield facet_item_presenter(facet.config, val, facet.key)
|
@@ -6,8 +6,8 @@
|
|
6
6
|
<h1 class="modal-title"><%= title %></h1>
|
7
7
|
<% end) %>
|
8
8
|
|
9
|
-
<button type="button" class="blacklight-modal-close btn-close close" data-dismiss="modal" aria-label="<%= t('blacklight.modal.close') %>">
|
10
|
-
<span aria-hidden="true">×</span>
|
9
|
+
<button type="button" class="blacklight-modal-close btn-close close" data-bs-dismiss="modal" data-dismiss="modal" aria-label="<%= t('blacklight.modal.close') %>">
|
10
|
+
<span aria-hidden="true" class="visually-hidden">×</span>
|
11
11
|
</button>
|
12
12
|
</div>
|
13
13
|
|
@@ -260,7 +260,7 @@ module Blacklight::Catalog
|
|
260
260
|
|
261
261
|
# Email Action (this will render the appropriate view on GET requests and process the form and send the email on POST requests)
|
262
262
|
def email_action documents
|
263
|
-
mail = RecordMailer.email_record(documents, { to: params[:to], message: params[:message] }, url_options)
|
263
|
+
mail = RecordMailer.email_record(documents, { to: params[:to], message: params[:message], config: blacklight_config }, url_options)
|
264
264
|
if mail.respond_to? :deliver_now
|
265
265
|
mail.deliver_now
|
266
266
|
else
|
@@ -271,7 +271,7 @@ module Blacklight::Catalog
|
|
271
271
|
# SMS action (this will render the appropriate view on GET requests and process the form and send the email on POST requests)
|
272
272
|
def sms_action documents
|
273
273
|
to = "#{params[:to].gsub(/[^\d]/, '')}@#{params[:carrier]}"
|
274
|
-
mail = RecordMailer.sms_record(documents, { to: to }, url_options)
|
274
|
+
mail = RecordMailer.sms_record(documents, { to: to, config: blacklight_config }, url_options)
|
275
275
|
if mail.respond_to? :deliver_now
|
276
276
|
mail.deliver_now
|
277
277
|
else
|
@@ -13,7 +13,9 @@ Blacklight = function() {
|
|
13
13
|
|
14
14
|
listeners: function () {
|
15
15
|
var listeners = [];
|
16
|
-
if (typeof
|
16
|
+
if (typeof Turbo !== 'undefined') {
|
17
|
+
listeners.push('turbo:load');
|
18
|
+
} else if (typeof Turbolinks !== 'undefined' && Turbolinks.supported) {
|
17
19
|
// Turbolinks 5
|
18
20
|
if (Turbolinks.BrowserAdapter) {
|
19
21
|
listeners.push('turbolinks:load');
|
@@ -41,6 +43,8 @@ Blacklight.listeners().forEach(function(listener) {
|
|
41
43
|
Blacklight.onLoad(function () {
|
42
44
|
const elem = document.querySelector('.no-js');
|
43
45
|
|
46
|
+
// The "no-js" class may already have been removed because this function is
|
47
|
+
// run on every turbo:load event, in that case, it won't find an element.
|
44
48
|
if (!elem) return;
|
45
49
|
|
46
50
|
elem.classList.remove('no-js')
|
@@ -120,7 +120,7 @@ Blacklight.modal.onFailure = function(jqXHR, textStatus, errorThrown) {
|
|
120
120
|
Blacklight.modal.receiveAjax = function (contents) {
|
121
121
|
// does it have a data- selector for container?
|
122
122
|
// important we don't execute script tags, we shouldn't.
|
123
|
-
// code modelled off of JQuery ajax.load. https://github.com/jquery/jquery/blob/
|
123
|
+
// code modelled off of JQuery ajax.load. https://github.com/jquery/jquery/blob/main/src/ajax/load.js?source=c#L62
|
124
124
|
var container = $('<div>').
|
125
125
|
append( jQuery.parseHTML(contents) ).find( Blacklight.modal.containerSelector ).first();
|
126
126
|
if (container.length !== 0) {
|
@@ -2,13 +2,25 @@
|
|
2
2
|
# This module provides the body of an email export based on the document's semantic values
|
3
3
|
module Blacklight::Document::Email
|
4
4
|
# Return a text string that will be the body of the email
|
5
|
-
def to_email_text
|
6
|
-
semantics = to_semantic_values
|
5
|
+
def to_email_text(config = nil)
|
7
6
|
body = []
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
|
8
|
+
if config
|
9
|
+
body = config.email_fields.map do |name, field|
|
10
|
+
values = [self[name]].flatten
|
11
|
+
"#{field.label} #{values.join(' ')}" if self[name].present?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Use to_semantic_values for backwards compatibility
|
16
|
+
if body.empty?
|
17
|
+
semantics = to_semantic_values
|
18
|
+
body << I18n.t('blacklight.email.text.title', value: semantics[:title].join(" ")) if semantics[:title].present?
|
19
|
+
body << I18n.t('blacklight.email.text.author', value: semantics[:author].join(" ")) if semantics[:author].present?
|
20
|
+
body << I18n.t('blacklight.email.text.format', value: semantics[:format].join(" ")) if semantics[:format].present?
|
21
|
+
body << I18n.t('blacklight.email.text.language', value: semantics[:language].join(" ")) if semantics[:language].present?
|
22
|
+
end
|
23
|
+
|
12
24
|
return body.join("\n") unless body.empty?
|
13
25
|
end
|
14
26
|
end
|
@@ -2,11 +2,23 @@
|
|
2
2
|
# This module provides the body of an email export based on the document's semantic values
|
3
3
|
module Blacklight::Document::Sms
|
4
4
|
# Return a text string that will be the body of the email
|
5
|
-
def to_sms_text
|
6
|
-
semantics = to_semantic_values
|
5
|
+
def to_sms_text(config = nil)
|
7
6
|
body = []
|
8
|
-
|
9
|
-
|
7
|
+
|
8
|
+
if config
|
9
|
+
body = config.sms_fields.map do |name, field|
|
10
|
+
values = [self[name]].flatten
|
11
|
+
"#{field.label} #{values.first}" if self[name].present?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Use to_semantic_values for backwards compatibility
|
16
|
+
if body.empty?
|
17
|
+
semantics = to_semantic_values
|
18
|
+
body << I18n.t('blacklight.sms.text.title', value: semantics[:title].first) if semantics[:title].present?
|
19
|
+
body << I18n.t('blacklight.sms.text.author', value: semantics[:author].first) if semantics[:author].present?
|
20
|
+
end
|
21
|
+
|
10
22
|
return body.join unless body.empty?
|
11
23
|
end
|
12
24
|
end
|
data/app/models/record_mailer.rb
CHANGED
@@ -3,7 +3,12 @@
|
|
3
3
|
class RecordMailer < ActionMailer::Base
|
4
4
|
def email_record(documents, details, url_gen_params)
|
5
5
|
title = begin
|
6
|
-
|
6
|
+
title_field = details[:config].email.title_field
|
7
|
+
if title_field
|
8
|
+
[documents.first[title_field]].flatten.first
|
9
|
+
else
|
10
|
+
documents.first.to_semantic_values[:title]
|
11
|
+
end
|
7
12
|
rescue
|
8
13
|
I18n.t('blacklight.email.text.default_title')
|
9
14
|
end
|
@@ -14,6 +19,7 @@ class RecordMailer < ActionMailer::Base
|
|
14
19
|
|
15
20
|
@documents = documents
|
16
21
|
@message = details[:message]
|
22
|
+
@config = details[:config]
|
17
23
|
@url_gen_params = url_gen_params
|
18
24
|
|
19
25
|
mail(to: details[:to], subject: subject)
|
@@ -21,7 +27,9 @@ class RecordMailer < ActionMailer::Base
|
|
21
27
|
|
22
28
|
def sms_record(documents, details, url_gen_params)
|
23
29
|
@documents = documents
|
30
|
+
@config = details[:config]
|
24
31
|
@url_gen_params = url_gen_params
|
32
|
+
|
25
33
|
mail(to: details[:to], subject: "")
|
26
34
|
end
|
27
35
|
end
|
@@ -56,6 +56,8 @@ module Blacklight
|
|
56
56
|
view_context.public_send(facet_config.helper_method, label_value)
|
57
57
|
elsif facet_config.query && facet_config.query[label_value]
|
58
58
|
facet_config.query[label_value][:label]
|
59
|
+
elsif value == Blacklight::SearchState::FilterField::MISSING
|
60
|
+
I18n.t("blacklight.search.facets.missing")
|
59
61
|
elsif facet_config.date
|
60
62
|
localization_options = facet_config.date == true ? {} : facet_config.date
|
61
63
|
I18n.l(Time.zone.parse(label_value), **localization_options)
|
@@ -101,6 +101,9 @@ module Blacklight
|
|
101
101
|
show: { top_level_config: :show },
|
102
102
|
citation: { parent_config: :show }
|
103
103
|
),
|
104
|
+
# SMS and Email configurations.
|
105
|
+
sms: ViewConfig.new,
|
106
|
+
email: ViewConfig.new,
|
104
107
|
# Configurations for specific types of index views
|
105
108
|
view: NestedOpenStructWithHashAccess.new(ViewConfig,
|
106
109
|
list: {},
|
@@ -167,6 +170,12 @@ module Blacklight
|
|
167
170
|
# solr fields to use for sorting results
|
168
171
|
define_field_access :sort_field
|
169
172
|
|
173
|
+
# solr fields to use in text message
|
174
|
+
define_field_access :sms_field
|
175
|
+
|
176
|
+
# solr fields to use in email message
|
177
|
+
define_field_access :email_field
|
178
|
+
|
170
179
|
def initialize(hash = {})
|
171
180
|
super(self.class.default_values.deep_dup.merge(hash))
|
172
181
|
yield(self) if block_given?
|
data/lib/blacklight/engine.rb
CHANGED
@@ -4,6 +4,8 @@ module Blacklight
|
|
4
4
|
class SearchState
|
5
5
|
# Modeling access to filter query parameters
|
6
6
|
class FilterField
|
7
|
+
MISSING = { missing: true }.freeze
|
8
|
+
|
7
9
|
# @param [Blacklight::Configuration::FacetField] config
|
8
10
|
attr_reader :config
|
9
11
|
|
@@ -25,7 +27,9 @@ module Blacklight
|
|
25
27
|
def add(item)
|
26
28
|
new_state = search_state.reset_search
|
27
29
|
|
28
|
-
if item.
|
30
|
+
if item.try(:missing)
|
31
|
+
# if this is a 'missing' facet value, the :fq is only for backwards compatibility
|
32
|
+
elsif item.respond_to?(:fq)
|
29
33
|
Array(item.fq).each do |f, v|
|
30
34
|
new_state = new_state.filter(f).add(v)
|
31
35
|
end
|
@@ -35,21 +39,28 @@ module Blacklight
|
|
35
39
|
return new_state.filter(item.field).add(item)
|
36
40
|
end
|
37
41
|
|
42
|
+
url_key = key
|
38
43
|
params = new_state.params
|
39
44
|
param = :f
|
40
45
|
value = as_url_parameter(item)
|
46
|
+
|
47
|
+
if value == Blacklight::SearchState::FilterField::MISSING
|
48
|
+
url_key = "-#{key}"
|
49
|
+
value = Blacklight::Engine.config.facet_missing_param
|
50
|
+
end
|
51
|
+
|
41
52
|
param = :f_inclusive if value.is_a?(Array)
|
42
53
|
|
43
54
|
# value could be a string
|
44
55
|
params[param] = (params[param] || {}).dup
|
45
56
|
|
46
57
|
if value.is_a? Array
|
47
|
-
params[param][
|
58
|
+
params[param][url_key] = value
|
48
59
|
elsif config.single
|
49
|
-
params[param][
|
60
|
+
params[param][url_key] = [value]
|
50
61
|
else
|
51
|
-
params[param][
|
52
|
-
params[param][
|
62
|
+
params[param][url_key] = Array(params[param][url_key] || []).dup
|
63
|
+
params[param][url_key].push(value)
|
53
64
|
end
|
54
65
|
|
55
66
|
new_state.reset(params)
|
@@ -63,19 +74,26 @@ module Blacklight
|
|
63
74
|
return new_state.filter(item.field).remove(item)
|
64
75
|
end
|
65
76
|
|
77
|
+
url_key = config.key
|
66
78
|
params = new_state.params
|
67
79
|
|
68
80
|
param = :f
|
69
81
|
value = as_url_parameter(item)
|
82
|
+
|
83
|
+
if value == Blacklight::SearchState::FilterField::MISSING
|
84
|
+
url_key = "-#{key}"
|
85
|
+
value = Blacklight::Engine.config.facet_missing_param
|
86
|
+
end
|
87
|
+
|
70
88
|
param = :f_inclusive if value.is_a?(Array)
|
71
89
|
|
72
90
|
# need to dup the facet values too,
|
73
91
|
# if the values aren't dup'd, then the values
|
74
92
|
# from the session will get remove in the show view...
|
75
93
|
params[param] = (params[param] || {}).dup
|
76
|
-
params[param][
|
94
|
+
params[param][url_key] = (params[param][url_key] || []).dup
|
77
95
|
|
78
|
-
collection = params[param][
|
96
|
+
collection = params[param][url_key]
|
79
97
|
# collection should be an array, because we link to ?f[key][]=value,
|
80
98
|
# however, Facebook (and maybe some other PHP tools) tranform that parameters
|
81
99
|
# into ?f[key][0]=value, which Rails interprets as a Hash.
|
@@ -84,18 +102,10 @@ module Blacklight
|
|
84
102
|
collection = collection.values
|
85
103
|
end
|
86
104
|
|
87
|
-
params[param][
|
88
|
-
params[param].delete(
|
105
|
+
params[param][url_key] = collection - Array(value)
|
106
|
+
params[param].delete(url_key) if params[param][url_key].empty?
|
89
107
|
params.delete(param) if params[param].empty?
|
90
108
|
|
91
|
-
# Handle missing field queries.
|
92
|
-
missing = I18n.t("blacklight.search.facets.missing")
|
93
|
-
if (item.respond_to?(:fq) && item.fq == "-#{key}:[* TO *]") ||
|
94
|
-
item == missing
|
95
|
-
params[param].delete("-#{key}:")
|
96
|
-
params[param].delete(key) if params[param][key] == [""]
|
97
|
-
end
|
98
|
-
|
99
109
|
new_state.reset(params)
|
100
110
|
end
|
101
111
|
|
@@ -104,8 +114,9 @@ module Blacklight
|
|
104
114
|
params = search_state.params
|
105
115
|
f = Array(params.dig(:f, key))
|
106
116
|
f_inclusive = [params.dig(:f_inclusive, key)] if params.dig(:f_inclusive, key).present?
|
117
|
+
f_missing = [Blacklight::SearchState::FilterField::MISSING] if params.dig(:f, "-#{key}")&.any? { |v| v == Blacklight::Engine.config.facet_missing_param }
|
107
118
|
|
108
|
-
f + (f_inclusive || [])
|
119
|
+
f + (f_inclusive || []) + (f_missing || [])
|
109
120
|
end
|
110
121
|
delegate :any?, to: :values
|
111
122
|
|
@@ -121,6 +132,8 @@ module Blacklight
|
|
121
132
|
|
122
133
|
if value.is_a?(Array)
|
123
134
|
(params.dig(:f_inclusive, key) || []).to_set == value.to_set
|
135
|
+
elsif value == Blacklight::SearchState::FilterField::MISSING
|
136
|
+
(params.dig(:f, "-#{key}") || []).include?(Blacklight::Engine.config.facet_missing_param)
|
124
137
|
else
|
125
138
|
(params.dig(:f, key) || []).include?(value)
|
126
139
|
end
|
@@ -130,7 +143,9 @@ module Blacklight
|
|
130
143
|
|
131
144
|
# TODO: this code is duplicated in Blacklight::FacetsHelperBehavior
|
132
145
|
def as_url_parameter(item)
|
133
|
-
if item.respond_to?
|
146
|
+
if item.respond_to?(:missing) && item.missing
|
147
|
+
Blacklight::SearchState::FilterField::MISSING
|
148
|
+
elsif item.respond_to? :value
|
134
149
|
item.value
|
135
150
|
else
|
136
151
|
item
|
@@ -171,7 +171,8 @@ module Blacklight::Solr::Response::Facets
|
|
171
171
|
# legacy solr facet.missing serialization
|
172
172
|
if value.nil?
|
173
173
|
i.label = I18n.t(:"blacklight.search.fields.facet.missing.#{facet_field_name}", default: [:"blacklight.search.facets.missing"])
|
174
|
-
i.fq = "-#{facet_field_name}:[* TO *]"
|
174
|
+
i.fq = "-#{facet_field_name}:[* TO *]" # this explicit fq is deprecated; the missing attribute below is a better thing to check for this case
|
175
|
+
i.value = Blacklight::SearchState::FilterField::MISSING
|
175
176
|
i.missing = true
|
176
177
|
end
|
177
178
|
|
@@ -10,7 +10,6 @@ module Blacklight::Solr
|
|
10
10
|
:add_facetting_to_solr, :add_solr_fields_to_query, :add_paging_to_solr,
|
11
11
|
:add_sorting_to_solr, :add_group_config_to_solr,
|
12
12
|
:add_facet_paging_to_solr, :add_adv_search_clauses,
|
13
|
-
:add_missing_field_query,
|
14
13
|
:add_additional_filters
|
15
14
|
]
|
16
15
|
end
|
@@ -82,19 +81,6 @@ module Blacklight::Solr
|
|
82
81
|
end
|
83
82
|
end
|
84
83
|
|
85
|
-
##
|
86
|
-
# Build and append a missing field query.
|
87
|
-
##
|
88
|
-
def add_missing_field_query(solr_parameters)
|
89
|
-
return unless solr_parameters["facet.missing"]
|
90
|
-
|
91
|
-
solr_parameters[:fq] = [] if solr_parameters[:fq].blank?
|
92
|
-
|
93
|
-
solr_parameters[:fq].append(*(blacklight_params["f"] || [])
|
94
|
-
.select { |f| f.match(/^-/) }
|
95
|
-
.map { |k, _v| "#{k}[* TO *]" })
|
96
|
-
end
|
97
|
-
|
98
84
|
def add_additional_filters(solr_parameters, additional_filters = nil)
|
99
85
|
q = additional_filters || @additional_filters
|
100
86
|
|
@@ -384,6 +370,8 @@ module Blacklight::Solr
|
|
384
370
|
elsif value.is_a?(Range)
|
385
371
|
prefix = "{!#{local_params.join(' ')}}" unless local_params.empty?
|
386
372
|
"#{prefix}#{solr_field}:[#{value.first} TO #{value.last}]"
|
373
|
+
elsif value == Blacklight::SearchState::FilterField::MISSING
|
374
|
+
"-#{solr_field}:[* TO *]"
|
387
375
|
else
|
388
376
|
"{!term f=#{solr_field}#{(' ' + local_params.join(' ')) unless local_params.empty?}}#{convert_to_term_value(value)}"
|
389
377
|
end
|
data/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "blacklight-frontend",
|
3
3
|
"version": "7.20.1",
|
4
|
-
"description": "[](https://travis-ci.com/projectblacklight/blacklight) [](http://badge.fury.io/rb/blacklight) [](https://coveralls.io/github/projectblacklight/blacklight?branch=main)",
|
5
5
|
"main": "app/assets/javascripts/blacklight",
|
6
6
|
"scripts": {
|
7
7
|
"js-compile-bundle": "shx cat app/javascript/blacklight/core.js app/javascript/blacklight/autocomplete.js app/javascript/blacklight/bookmark_toggle.js app/javascript/blacklight/button_focus.js app/javascript/blacklight/checkbox_submit.js app/javascript/blacklight/facet_load.js app/javascript/blacklight/modal.js app/javascript/blacklight/search_context.js | shx sed \"s/^(import|export).*//\" | babel --filename app/javascript/blacklight/blacklight.js > app/assets/javascripts/blacklight/blacklight.js"
|
@@ -23,8 +23,10 @@
|
|
23
23
|
"devDependencies": {
|
24
24
|
"@babel/cli": "^7.2.3",
|
25
25
|
"@babel/core": "^7.2.3",
|
26
|
+
"@babel/preset-env": "^7.16.0",
|
26
27
|
"shx": "^0.3.2"
|
27
28
|
},
|
29
|
+
"browserslist": "> 0.25%, not dead",
|
28
30
|
"dependencies": {
|
29
31
|
"bloodhound-js": "^1.2.3",
|
30
32
|
"bootstrap": ">=4.3.1 <6.0.0",
|
@@ -501,6 +501,12 @@ RSpec.describe CatalogController, api: true do
|
|
501
501
|
end
|
502
502
|
|
503
503
|
describe "email", api: false do
|
504
|
+
let(:config) { Blacklight::Configuration.new }
|
505
|
+
|
506
|
+
before do
|
507
|
+
allow(controller).to receive(:blacklight_config).and_return(config)
|
508
|
+
end
|
509
|
+
|
504
510
|
it "gives error if no TO parameter" do
|
505
511
|
post :email, params: { id: doc_id }
|
506
512
|
expect(request.flash[:error]).to eq "You must enter a recipient in order to send this message"
|
@@ -518,7 +524,7 @@ RSpec.describe CatalogController, api: true do
|
|
518
524
|
|
519
525
|
it "redirects back to the record upon success" do
|
520
526
|
allow(RecordMailer).to receive(:email_record)
|
521
|
-
.with(anything, { to: 'test_email@projectblacklight.org', message: 'xyz' }, hash_including(host: 'test.host'))
|
527
|
+
.with(anything, { to: 'test_email@projectblacklight.org', message: 'xyz', config: config }, hash_including(host: 'test.host'))
|
522
528
|
.and_return double(deliver: nil)
|
523
529
|
post :email, params: { id: doc_id, to: 'test_email@projectblacklight.org', message: 'xyz' }
|
524
530
|
expect(request.flash[:error]).to be_nil
|
@@ -533,6 +539,12 @@ RSpec.describe CatalogController, api: true do
|
|
533
539
|
end
|
534
540
|
|
535
541
|
describe "sms", api: false do
|
542
|
+
let(:config) { Blacklight::Configuration.new }
|
543
|
+
|
544
|
+
before do
|
545
|
+
allow(controller).to receive(:blacklight_config).and_return(config)
|
546
|
+
end
|
547
|
+
|
536
548
|
it "gives error if no phone number is given" do
|
537
549
|
post :sms, params: { id: doc_id, carrier: 'att' }
|
538
550
|
expect(request.flash[:error]).to eq "You must enter a recipient's phone number in order to send this message"
|
@@ -562,7 +574,7 @@ RSpec.describe CatalogController, api: true do
|
|
562
574
|
it "sends to the appropriate carrier email address" do
|
563
575
|
expect(RecordMailer)
|
564
576
|
.to receive(:sms_record)
|
565
|
-
.with(anything, { to: '5555555555@txt.att.net' }, hash_including(host: 'test.host'))
|
577
|
+
.with(anything, { to: '5555555555@txt.att.net', config: config }, hash_including(host: 'test.host'))
|
566
578
|
.and_return double(deliver: nil)
|
567
579
|
post :sms, params: { id: doc_id, to: '5555555555', carrier: 'txt.att.net' }
|
568
580
|
end
|
data/spec/features/axe_spec.rb
CHANGED
@@ -1,34 +1,33 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RSpec.describe 'Accessibility testing', api: false, js: true do
|
4
|
-
|
4
|
+
it 'validates the home page' do
|
5
5
|
visit root_path
|
6
6
|
expect(page).to be_accessible
|
7
7
|
end
|
8
8
|
|
9
|
-
|
9
|
+
it 'validates the catalog page' do
|
10
10
|
visit root_path
|
11
11
|
fill_in "q", with: 'history'
|
12
12
|
click_button 'search'
|
13
13
|
|
14
|
-
|
15
|
-
expect(page).to be_accessible(skipping: ['aria-allowed-role'])
|
14
|
+
expect(page).to be_accessible
|
16
15
|
|
17
16
|
within '.card.blacklight-language_ssim' do
|
18
17
|
click_button 'Language'
|
19
18
|
click_link "Tibetan"
|
20
19
|
end
|
21
20
|
|
22
|
-
expect(page).to be_accessible
|
21
|
+
expect(page).to be_accessible
|
23
22
|
end
|
24
23
|
|
25
|
-
|
24
|
+
it 'validates the single results page' do
|
26
25
|
visit solr_document_path('2007020969')
|
27
26
|
expect(page).to be_accessible
|
28
27
|
end
|
29
28
|
|
30
29
|
def be_accessible(skipping: [])
|
31
30
|
# typeahead does funny things with the search bar
|
32
|
-
be_axe_clean.excluding('.tt-hint').skipping(skipping + [('color-contrast' if Bootstrap::VERSION < '5')])
|
31
|
+
be_axe_clean.excluding('.tt-hint').skipping(skipping + [('color-contrast' if Bootstrap::VERSION < '5')].compact)
|
33
32
|
end
|
34
33
|
end
|
@@ -32,8 +32,12 @@ RSpec.describe "Facet missing" do
|
|
32
32
|
end
|
33
33
|
|
34
34
|
context "unselecting the facet missing facet" do
|
35
|
-
it "unselects the
|
36
|
-
visit root_path
|
35
|
+
it "unselects the missing field facet" do
|
36
|
+
visit root_path
|
37
|
+
|
38
|
+
within "#facet-subject_geo_ssim" do
|
39
|
+
click_link "[Missing]"
|
40
|
+
end
|
37
41
|
|
38
42
|
within "#facet-subject_geo_ssim" do
|
39
43
|
click_link "remove"
|
@@ -45,8 +49,12 @@ RSpec.describe "Facet missing" do
|
|
45
49
|
end
|
46
50
|
|
47
51
|
context "unselecting the facet missing constraint" do
|
48
|
-
it "unselects the
|
49
|
-
visit root_path
|
52
|
+
it "unselects the missing field facet" do
|
53
|
+
visit root_path
|
54
|
+
|
55
|
+
within "#facet-subject_geo_ssim" do
|
56
|
+
click_link "[Missing]"
|
57
|
+
end
|
50
58
|
|
51
59
|
within ".filter-subject_geo_ssim" do
|
52
60
|
click_link "Remove constraint Region: [Missing]"
|
@@ -162,28 +162,14 @@ RSpec.describe Blacklight::SearchState::FilterField do
|
|
162
162
|
|
163
163
|
context "With facet.missing field" do
|
164
164
|
let(:params) do
|
165
|
-
{ f: {
|
165
|
+
{ f: { "-some_field": ["[* TO *]"] } }
|
166
166
|
end
|
167
167
|
|
168
168
|
it "removes facet.missing facet params" do
|
169
169
|
filter = search_state.filter("some_field")
|
170
|
-
new_state = filter.remove(OpenStruct.new(
|
170
|
+
new_state = filter.remove(OpenStruct.new(key: 'some_field', missing: true))
|
171
171
|
|
172
|
-
expect(new_state.params).to eq(
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
context "With facet.missing field value" do
|
177
|
-
let(:params) do
|
178
|
-
{ f: { some_field: [""], "-some_field:": [""] } }
|
179
|
-
end
|
180
|
-
|
181
|
-
it "removes facet.missing facet params" do
|
182
|
-
missing = I18n.t("blacklight.search.facets.missing")
|
183
|
-
filter = search_state.filter("some_field")
|
184
|
-
new_state = filter.remove(missing)
|
185
|
-
|
186
|
-
expect(new_state.params).to eq("f" => {})
|
172
|
+
expect(new_state.params).to eq({})
|
187
173
|
end
|
188
174
|
end
|
189
175
|
end
|
@@ -543,6 +543,98 @@ RSpec.describe "Blacklight::Configuration", api: true do
|
|
543
543
|
end
|
544
544
|
end
|
545
545
|
|
546
|
+
describe "add_sms_field" do
|
547
|
+
it "takes hash form" do
|
548
|
+
config.add_sms_field("title_tsim", label: "Title")
|
549
|
+
|
550
|
+
expect(config.sms_fields["title_tsim"]).not_to be_nil
|
551
|
+
expect(config.sms_fields["title_tsim"].label).to eq "Title"
|
552
|
+
end
|
553
|
+
|
554
|
+
it "takes ShowField argument" do
|
555
|
+
config.add_sms_field("title_tsim", Blacklight::Configuration::SmsField.new(field: "title_display", label: "Title"))
|
556
|
+
|
557
|
+
expect(config.sms_fields["title_tsim"]).not_to be_nil
|
558
|
+
expect(config.sms_fields["title_tsim"].label).to eq "Title"
|
559
|
+
end
|
560
|
+
|
561
|
+
it "takes block form" do
|
562
|
+
config.add_sms_field("title_tsim") do |f|
|
563
|
+
f.label = "Title"
|
564
|
+
end
|
565
|
+
|
566
|
+
expect(config.sms_fields["title_tsim"]).not_to be_nil
|
567
|
+
expect(config.sms_fields["title_tsim"].label).to eq "Title"
|
568
|
+
end
|
569
|
+
|
570
|
+
it "creates default label humanized from field" do
|
571
|
+
config.add_sms_field("my_custom_field")
|
572
|
+
|
573
|
+
expect(config.sms_fields["my_custom_field"].label).to eq "My Custom Field"
|
574
|
+
end
|
575
|
+
|
576
|
+
it "raises on nil solr field name" do
|
577
|
+
expect { config.add_sms_field(nil) }.to raise_error ArgumentError
|
578
|
+
end
|
579
|
+
|
580
|
+
it "takes wild-carded field names and dereference them to solr fields" do
|
581
|
+
allow(config).to receive(:reflected_fields).and_return(
|
582
|
+
"some_field_display" => {},
|
583
|
+
"another_field_display" => {},
|
584
|
+
"a_facet_field" => {}
|
585
|
+
)
|
586
|
+
config.add_sms_field "*_display"
|
587
|
+
|
588
|
+
expect(config.sms_fields.keys).to eq %w[some_field_display another_field_display]
|
589
|
+
end
|
590
|
+
end
|
591
|
+
|
592
|
+
describe "add_email_field" do
|
593
|
+
it "takes hash form" do
|
594
|
+
config.add_email_field("title_tsim", label: "Title")
|
595
|
+
|
596
|
+
expect(config.email_fields["title_tsim"]).not_to be_nil
|
597
|
+
expect(config.email_fields["title_tsim"].label).to eq "Title"
|
598
|
+
end
|
599
|
+
|
600
|
+
it "takes ShowField argument" do
|
601
|
+
config.add_email_field("title_tsim", Blacklight::Configuration::EmailField.new(field: "title_display", label: "Title"))
|
602
|
+
|
603
|
+
expect(config.email_fields["title_tsim"]).not_to be_nil
|
604
|
+
expect(config.email_fields["title_tsim"].label).to eq "Title"
|
605
|
+
end
|
606
|
+
|
607
|
+
it "takes block form" do
|
608
|
+
config.add_email_field("title_tsim") do |f|
|
609
|
+
f.label = "Title"
|
610
|
+
end
|
611
|
+
|
612
|
+
expect(config.email_fields["title_tsim"]).not_to be_nil
|
613
|
+
expect(config.email_fields["title_tsim"].label).to eq "Title"
|
614
|
+
end
|
615
|
+
|
616
|
+
it "creates default label humanized from field" do
|
617
|
+
config.add_email_field("my_custom_field")
|
618
|
+
|
619
|
+
expect(config.email_fields["my_custom_field"].label).to eq "My Custom Field"
|
620
|
+
end
|
621
|
+
|
622
|
+
it "raises on nil solr field name" do
|
623
|
+
expect { config.add_email_field(nil) }.to raise_error ArgumentError
|
624
|
+
end
|
625
|
+
|
626
|
+
it "takes wild-carded field names and dereference them to solr fields" do
|
627
|
+
allow(config).to receive(:reflected_fields).and_return(
|
628
|
+
"some_field_display" => {},
|
629
|
+
"another_field_display" => {},
|
630
|
+
"a_facet_field" => {}
|
631
|
+
)
|
632
|
+
config.add_email_field "*_display"
|
633
|
+
|
634
|
+
expect(config.email_fields.keys).to eq %w[some_field_display another_field_display]
|
635
|
+
end
|
636
|
+
end
|
637
|
+
|
546
638
|
describe "#default_search_field" do
|
547
639
|
it "uses the field with a :default key" do
|
548
640
|
config.add_search_field('search_field_1')
|
@@ -1,6 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RSpec.describe "Blacklight::Document::Email" do
|
4
|
+
let(:config) do
|
5
|
+
Blacklight::Configuration.new
|
6
|
+
end
|
7
|
+
|
4
8
|
before(:all) do
|
5
9
|
SolrDocument.use_extension(Blacklight::Document::Email)
|
6
10
|
end
|
@@ -22,4 +26,32 @@ RSpec.describe "Blacklight::Document::Email" do
|
|
22
26
|
doc = SolrDocument.new(id: "1234")
|
23
27
|
expect(doc.to_email_text).to be_nil
|
24
28
|
end
|
29
|
+
|
30
|
+
context "we pass in configuration with email fields set" do
|
31
|
+
it "uses the email fields for to_email_text" do
|
32
|
+
config.add_email_field("foo", label: "Foo:")
|
33
|
+
config.add_email_field("bar", label: "Bar:")
|
34
|
+
doc = SolrDocument.new(id: "1234", foo: ["Fuzz Fuzz", "Fizz Fizz"], bar: ["Buzz Buzz", "Bizz Bizz"])
|
35
|
+
|
36
|
+
expect(doc.to_email_text(config)).to eq("Foo: Fuzz Fuzz Fizz Fizz\nBar: Buzz Buzz Bizz Bizz")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "we pass in configuration with email fields no set" do
|
41
|
+
it "falls back on default semantics setup" do
|
42
|
+
doc = SolrDocument.new(id: "1234", title_tsim: ["My Title", "My Alt. Title"])
|
43
|
+
email_body = doc.to_email_text(config)
|
44
|
+
expect(email_body).to match(/Title: My Title/)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "document field is single valued" do
|
49
|
+
it "handles the single value field correctly" do
|
50
|
+
config.add_email_field("foo", label: "Foo:")
|
51
|
+
config.add_email_field("bar", label: "Bar:")
|
52
|
+
doc = SolrDocument.new(id: "1234", foo: "Fuzz Fuzz", bar: ["Buzz Buzz", "Bizz Bizz"])
|
53
|
+
|
54
|
+
expect(doc.to_email_text(config)).to eq("Foo: Fuzz Fuzz\nBar: Buzz Buzz Bizz Bizz")
|
55
|
+
end
|
56
|
+
end
|
25
57
|
end
|
@@ -1,6 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RSpec.describe "Blacklight::Document::Email" do
|
4
|
+
let(:config) do
|
5
|
+
Blacklight::Configuration.new
|
6
|
+
end
|
7
|
+
|
4
8
|
before(:all) do
|
5
9
|
SolrDocument.use_extension(Blacklight::Document::Sms)
|
6
10
|
end
|
@@ -22,4 +26,33 @@ RSpec.describe "Blacklight::Document::Email" do
|
|
22
26
|
doc = SolrDocument.new(id: "1234")
|
23
27
|
expect(doc.to_sms_text).to be_nil
|
24
28
|
end
|
29
|
+
|
30
|
+
context "we pass in configuration with sms fields set" do
|
31
|
+
it "uses the sms fields for to_sms_text" do
|
32
|
+
config.add_sms_field("foo", label: "Foo:")
|
33
|
+
config.add_sms_field("bar", label: " by")
|
34
|
+
doc = SolrDocument.new(id: "1234", foo: ["Fuzz Fuzz", "Fizz Fizz"], bar: ["Buzz Buzz", "Bizz Bizz"])
|
35
|
+
|
36
|
+
expect(doc.to_sms_text(config)).to eq("Foo: Fuzz Fuzz by Buzz Buzz")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "we pass in configuration with sms fields no set" do
|
41
|
+
it "falls back on default semantics setup" do
|
42
|
+
doc = SolrDocument.new(id: "1234", title_tsim: ["My Title", "My Alt. Title"])
|
43
|
+
sms_text = doc.to_sms_text(config)
|
44
|
+
expect(sms_text).to match(/My Title/)
|
45
|
+
expect(sms_text).not_to match(/My Alt\. Title/)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "document field is single valued" do
|
50
|
+
it "handles the single value field correctly" do
|
51
|
+
config.add_sms_field("foo", label: "Foo:")
|
52
|
+
config.add_sms_field("bar", label: " by")
|
53
|
+
doc = SolrDocument.new(id: "1234", foo: "Fuzz Fuzz", bar: ["Buzz Buzz", "Bizz Bizz"])
|
54
|
+
|
55
|
+
expect(doc.to_sms_text(config)).to eq("Foo: Fuzz Fuzz by Buzz Buzz")
|
56
|
+
end
|
57
|
+
end
|
25
58
|
end
|
@@ -155,7 +155,7 @@ RSpec.describe Blacklight::Solr::Response::Facets, api: true do
|
|
155
155
|
end
|
156
156
|
|
157
157
|
it "marks the facet.missing field with a human-readable label and fq" do
|
158
|
-
missing = subject.aggregations["some_field"].items.find
|
158
|
+
missing = subject.aggregations["some_field"].items.find(&:missing)
|
159
159
|
|
160
160
|
expect(missing.label).to eq "[Missing]"
|
161
161
|
expect(missing.fq).to eq "-some_field:[* TO *]"
|
@@ -27,10 +27,6 @@ RSpec.describe Blacklight::Solr::SearchBuilderBehavior, api: true do
|
|
27
27
|
it "uses the class-level default_processor_chain" do
|
28
28
|
expect(subject.processor_chain).to eq search_builder_class.default_processor_chain
|
29
29
|
end
|
30
|
-
|
31
|
-
it "appends the :add_missing_field_query processor" do
|
32
|
-
expect(subject.processor_chain).to include(:add_missing_field_query)
|
33
|
-
end
|
34
30
|
end
|
35
31
|
|
36
32
|
context 'with merged parameters from the defaults + the search field' do
|
@@ -826,13 +822,4 @@ RSpec.describe Blacklight::Solr::SearchBuilderBehavior, api: true do
|
|
826
822
|
expect(subject.to_hash).to include q: '{!lucene}id:(1 OR 2 OR 3)'
|
827
823
|
end
|
828
824
|
end
|
829
|
-
|
830
|
-
describe "#add_missing_field_query" do
|
831
|
-
it "precesses facet.missing query" do
|
832
|
-
subject.with("f" => { "-hello:" => [""] })
|
833
|
-
solr_params = { "facet.missing" => true, fq: [] }
|
834
|
-
|
835
|
-
expect(subject.add_missing_field_query(solr_params)).to eq(["-hello:[* TO *]"])
|
836
|
-
end
|
837
|
-
end
|
838
825
|
end
|
@@ -1,17 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
RSpec.describe RecordMailer do
|
4
|
+
let(:config) do
|
5
|
+
Blacklight::Configuration.new
|
6
|
+
end
|
7
|
+
|
8
|
+
let(:document) do
|
9
|
+
SolrDocument.new(id: "123456", format: ["book"], title_tsim: "The horn", language_ssim: "English", author_tsim: "Janetzky, Kurt")
|
10
|
+
end
|
11
|
+
|
4
12
|
before do
|
5
13
|
allow(described_class).to receive(:default).and_return(from: 'no-reply@projectblacklight.org')
|
6
14
|
SolrDocument.use_extension(Blacklight::Document::Email)
|
7
15
|
SolrDocument.use_extension(Blacklight::Document::Sms)
|
8
|
-
document = SolrDocument.new(id: "123456", format: ["book"], title_tsim: "The horn", language_ssim: "English", author_tsim: "Janetzky, Kurt")
|
9
16
|
@documents = [document]
|
10
17
|
end
|
11
18
|
|
12
19
|
describe "email" do
|
13
20
|
before do
|
14
|
-
details = { to: 'test@test.com', message: "This is my message" }
|
21
|
+
details = { to: 'test@test.com', message: "This is my message", config: config }
|
15
22
|
@email = described_class.email_record(@documents, details, host: 'projectblacklight.org', protocol: 'https')
|
16
23
|
end
|
17
24
|
|
@@ -42,6 +49,27 @@ RSpec.describe RecordMailer do
|
|
42
49
|
@https_email = described_class.email_record(@documents, details, host: 'projectblacklight.org', protocol: 'https')
|
43
50
|
expect(@https_email.body).to match %r{https://projectblacklight.org/}
|
44
51
|
end
|
52
|
+
|
53
|
+
context "email title_field is configured and multi valued" do
|
54
|
+
let(:document) { SolrDocument.new(id: "123456", foo: ["Fizz Fizz", "Fuzz Fuzz"], format: ["book"], title_tsim: "The horn", language_ssim: "English", author_tsim: "Janetzky, Kurt") }
|
55
|
+
|
56
|
+
it "uses configured email title_field" do
|
57
|
+
config.email.title_field = "foo"
|
58
|
+
expect(@email.subject).to match("Fizz Fizz")
|
59
|
+
expect(@email.subject).not_to match("Fuzz Fuzz")
|
60
|
+
expect(@email.subject).not_to match("The horn")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "email title_field is configured and single valued" do
|
65
|
+
let(:document) { SolrDocument.new(id: "123456", foo: "Fizz Fizz", format: ["book"], title_tsim: "The horn", language_ssim: "English", author_tsim: "Janetzky, Kurt") }
|
66
|
+
|
67
|
+
it "uses configured email title_field" do
|
68
|
+
config.email.title_field = "foo"
|
69
|
+
expect(@email.subject).to match("Fizz Fizz")
|
70
|
+
expect(@email.subject).not_to match("The horn")
|
71
|
+
end
|
72
|
+
end
|
45
73
|
end
|
46
74
|
|
47
75
|
describe "SMS" do
|
data/spec/spec_helper.rb
CHANGED
@@ -10,9 +10,6 @@ SimpleCov.start do
|
|
10
10
|
add_filter "/spec/"
|
11
11
|
end
|
12
12
|
|
13
|
-
require 'rsolr'
|
14
|
-
require 'blacklight'
|
15
|
-
|
16
13
|
require 'engine_cart'
|
17
14
|
EngineCart.load_application!
|
18
15
|
|
@@ -25,6 +22,9 @@ require 'selenium-webdriver'
|
|
25
22
|
require 'equivalent-xml'
|
26
23
|
require 'axe-rspec'
|
27
24
|
|
25
|
+
require 'rsolr'
|
26
|
+
require 'blacklight'
|
27
|
+
|
28
28
|
Capybara.javascript_driver = :headless_chrome
|
29
29
|
|
30
30
|
Capybara.register_driver :headless_chrome do |app|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blacklight
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.
|
4
|
+
version: 7.21.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Rochkind
|
@@ -14,10 +14,10 @@ authors:
|
|
14
14
|
- Dan Funk
|
15
15
|
- Naomi Dushay
|
16
16
|
- Justin Coyne
|
17
|
-
autorequire:
|
17
|
+
autorequire:
|
18
18
|
bindir: exe
|
19
19
|
cert_chain: []
|
20
|
-
date: 2021-11-
|
20
|
+
date: 2021-11-16 00:00:00.000000000 Z
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
23
23
|
name: rails
|
@@ -378,6 +378,7 @@ executables: []
|
|
378
378
|
extensions: []
|
379
379
|
extra_rdoc_files: []
|
380
380
|
files:
|
381
|
+
- ".babelrc"
|
381
382
|
- ".docker/app/Dockerfile"
|
382
383
|
- ".docker/app/entrypoint.sh"
|
383
384
|
- ".env"
|
@@ -918,7 +919,7 @@ homepage: http://projectblacklight.org/
|
|
918
919
|
licenses:
|
919
920
|
- Apache 2.0
|
920
921
|
metadata: {}
|
921
|
-
post_install_message:
|
922
|
+
post_install_message:
|
922
923
|
rdoc_options: []
|
923
924
|
require_paths:
|
924
925
|
- lib
|
@@ -933,8 +934,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
933
934
|
- !ruby/object:Gem::Version
|
934
935
|
version: '0'
|
935
936
|
requirements: []
|
936
|
-
rubygems_version: 3.
|
937
|
-
signing_key:
|
937
|
+
rubygems_version: 3.2.3
|
938
|
+
signing_key:
|
938
939
|
specification_version: 4
|
939
940
|
summary: Blacklight provides a discovery interface for any Solr (http://lucene.apache.org/solr)
|
940
941
|
index.
|