blacklight 7.20.0 → 7.21.2
Sign up to get free protection for your applications and to get access to all the features.
- 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 +46 -27
- 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/helpers/blacklight/render_partials_helper_behavior.rb +4 -1
- data/app/javascript/blacklight/core.js +12 -3
- 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/bookmarks/index.html.erb +1 -1
- data/app/views/catalog/_search_results.html.erb +1 -1
- data/app/views/record_mailer/sms_record.text.erb +1 -1
- data/blacklight.gemspec +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 +4 -2
- 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 +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 689d00beb305c757d023bd04cbbe2a25c103d33bd510dbf66919157623091fea
|
4
|
+
data.tar.gz: f331369f02497dffde92e2b6869fcd5db1daf7d9ceb1b1ca15faa1b42ca93e0e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 87dbb644ca803013438f197b3ad040b6f1c13c58945deae560fe8f2dfc27a5ed790ac5539c68d4121bad61da1aea7c375095cbcc504616906060bd7fc29a180d
|
7
|
+
data.tar.gz: fba8f46b736beb2373e36effd81b335b3e70ef7cdba5c8888a3169fe73e15ddd877857b45f267cd6ccba47e2248b36c3f242f277c27be6eabae12370425534b3
|
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.2
|
@@ -1,18 +1,22 @@
|
|
1
|
-
|
1
|
+
"use strict";
|
2
|
+
|
3
|
+
var 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,10 +41,14 @@ 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
|
+
|
47
|
+
if (!elem) return;
|
41
48
|
elem.classList.remove('no-js');
|
42
49
|
elem.classList.add('js');
|
43
50
|
});
|
51
|
+
window.Blacklight = Blacklight;
|
44
52
|
/*global Bloodhound */
|
45
53
|
|
46
54
|
Blacklight.onLoad(function () {
|
@@ -86,7 +94,7 @@ Blacklight.onLoad(function () {
|
|
86
94
|
$(Blacklight.doBookmarkToggleBehavior.selector).blCheckboxSubmit({
|
87
95
|
// cssClass is added to elements added, plus used for id base
|
88
96
|
cssClass: 'toggle-bookmark',
|
89
|
-
success: function (checked, response) {
|
97
|
+
success: function success(checked, response) {
|
90
98
|
if (response.bookmarks) {
|
91
99
|
$('[data-role=bookmark-counter]').text(response.bookmarks.count);
|
92
100
|
}
|
@@ -104,8 +112,8 @@ Blacklight.onLoad(function () {
|
|
104
112
|
// Button clicks should change focus. As of 10/3/19, Firefox for Mac and
|
105
113
|
// Safari both do not set focus to a button on button click.
|
106
114
|
// See https://zellwk.com/blog/inconsistent-button-behavior/ for background information
|
107
|
-
document.querySelectorAll('button.collapse-toggle').forEach(button
|
108
|
-
button.addEventListener('click', ()
|
115
|
+
document.querySelectorAll('button.collapse-toggle').forEach(function (button) {
|
116
|
+
button.addEventListener('click', function () {
|
109
117
|
event.target.focus();
|
110
118
|
});
|
111
119
|
});
|
@@ -192,12 +200,12 @@ Blacklight.onLoad(function () {
|
|
192
200
|
dataType: 'json',
|
193
201
|
type: form.attr('method').toUpperCase(),
|
194
202
|
data: form.serialize(),
|
195
|
-
error: function () {
|
203
|
+
error: function error() {
|
196
204
|
label.removeAttr('disabled');
|
197
205
|
checkbox.removeAttr('disabled');
|
198
206
|
options.error.call();
|
199
207
|
},
|
200
|
-
success: function (data, status, xhr) {
|
208
|
+
success: function success(data, status, xhr) {
|
201
209
|
//if app isn't running at all, xhr annoyingly
|
202
210
|
//reports success with status 0.
|
203
211
|
if (xhr.status != 0) {
|
@@ -223,10 +231,10 @@ Blacklight.onLoad(function () {
|
|
223
231
|
$.fn.blCheckboxSubmit.defaults = {
|
224
232
|
//cssClass is added to elements added, plus used for id base
|
225
233
|
cssClass: 'blCheckboxSubmit',
|
226
|
-
error: function () {
|
234
|
+
error: function error() {
|
227
235
|
alert("Error");
|
228
236
|
},
|
229
|
-
success: function () {} //callback
|
237
|
+
success: function success() {} //callback
|
230
238
|
|
231
239
|
};
|
232
240
|
})(jQuery);
|
@@ -242,12 +250,12 @@ Blacklight.doResizeFacetLabelsAndCounts = function () {
|
|
242
250
|
}
|
243
251
|
|
244
252
|
document.querySelectorAll('.facet-values, .pivot-facet').forEach(function (elem) {
|
245
|
-
|
253
|
+
var nodes = elem.querySelectorAll('.facet-count'); // TODO: when we drop ie11 support, this can become the spread operator:
|
246
254
|
|
247
|
-
|
255
|
+
var longest = Array.from(nodes).sort(longer)[0];
|
248
256
|
|
249
257
|
if (longest && longest.textContent) {
|
250
|
-
|
258
|
+
var width = longest.textContent.length + 1 + 'ch';
|
251
259
|
elem.querySelector('.facet-count').style.width = width;
|
252
260
|
}
|
253
261
|
});
|
@@ -364,7 +372,7 @@ Blacklight.modal.onFailure = function (jqXHR, textStatus, errorThrown) {
|
|
364
372
|
Blacklight.modal.receiveAjax = function (contents) {
|
365
373
|
// does it have a data- selector for container?
|
366
374
|
// important we don't execute script tags, we shouldn't.
|
367
|
-
// code modelled off of JQuery ajax.load. https://github.com/jquery/jquery/blob/
|
375
|
+
// code modelled off of JQuery ajax.load. https://github.com/jquery/jquery/blob/main/src/ajax/load.js?source=c#L62
|
368
376
|
var container = $('<div>').append(jQuery.parseHTML(contents)).find(Blacklight.modal.containerSelector).first();
|
369
377
|
|
370
378
|
if (container.length !== 0) {
|
@@ -442,14 +450,26 @@ Blacklight.doSearchContextBehavior = function () {
|
|
442
450
|
return Blacklight.do_search_context_behavior();
|
443
451
|
}
|
444
452
|
|
445
|
-
|
453
|
+
var elements = document.querySelectorAll('a[data-context-href]'); // Equivalent to Array.from(), but supports ie11
|
446
454
|
|
447
|
-
|
455
|
+
var nodes = Array.prototype.slice.call(elements);
|
448
456
|
nodes.forEach(function (element) {
|
449
457
|
element.addEventListener('click', function (e) {
|
450
458
|
Blacklight.handleSearchContextMethod.call(e.currentTarget, e);
|
451
459
|
});
|
452
460
|
});
|
461
|
+
};
|
462
|
+
|
463
|
+
Blacklight.csrfToken = function () {
|
464
|
+
var _document$querySelect;
|
465
|
+
|
466
|
+
return (_document$querySelect = document.querySelector('meta[name=csrf-token]')) === null || _document$querySelect === void 0 ? void 0 : _document$querySelect.content;
|
467
|
+
};
|
468
|
+
|
469
|
+
Blacklight.csrfParam = function () {
|
470
|
+
var _document$querySelect2;
|
471
|
+
|
472
|
+
return (_document$querySelect2 = document.querySelector('meta[name=csrf-param]')) === null || _document$querySelect2 === void 0 ? void 0 : _document$querySelect2.content;
|
453
473
|
}; // this is the Rails.handleMethod with a couple adjustments, described inline:
|
454
474
|
// first, we're attaching this directly to the event handler, so we can check for meta-keys
|
455
475
|
|
@@ -462,22 +482,21 @@ Blacklight.handleSearchContextMethod = function (event) {
|
|
462
482
|
|
463
483
|
var link = this; // instead of using the normal href, we need to use the context href instead
|
464
484
|
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
485
|
+
var href = link.getAttribute('data-context-href');
|
486
|
+
var target = link.getAttribute('target');
|
487
|
+
var csrfToken = Blacklight.csrfToken();
|
488
|
+
var csrfParam = Blacklight.csrfParam();
|
489
|
+
var form = document.createElement('form');
|
470
490
|
form.method = 'post';
|
471
491
|
form.action = href;
|
472
|
-
|
473
|
-
<input name="redirect" value="${link.getAttribute('href')}" type="hidden" />`; // check for meta keys.. if set, we should open in a new tab
|
492
|
+
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
|
474
493
|
|
475
494
|
if (event.metaKey || event.ctrlKey) {
|
476
495
|
target = '_blank';
|
477
496
|
}
|
478
497
|
|
479
498
|
if (csrfParam !== undefined && csrfToken !== undefined) {
|
480
|
-
formContent +=
|
499
|
+
formContent += "<input name=\"".concat(csrfParam, "\" value=\"").concat(csrfToken, "\" type=\"hidden\" />");
|
481
500
|
} // Must trigger submit by click on a button, else "submit" event handler won't work!
|
482
501
|
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/submit
|
483
502
|
|
@@ -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
|
@@ -9,7 +9,10 @@ module Blacklight::RenderPartialsHelperBehavior
|
|
9
9
|
# @param [Hash] locals to pass to the render call
|
10
10
|
# @return [String]
|
11
11
|
def render_document_index documents = nil, locals = {}
|
12
|
-
|
12
|
+
unless documents
|
13
|
+
Deprecation.warn(self, "Calling render_document_index without documents is deprecated and will be removed in version 8")
|
14
|
+
documents = @response.documents
|
15
|
+
end
|
13
16
|
render_document_index_with_view(document_index_view_type, documents, locals)
|
14
17
|
end
|
15
18
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
Blacklight = function() {
|
1
|
+
const Blacklight = function() {
|
2
2
|
var buffer = new Array;
|
3
3
|
return {
|
4
4
|
onLoad: function(func) {
|
@@ -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');
|
@@ -39,7 +41,14 @@ Blacklight.listeners().forEach(function(listener) {
|
|
39
41
|
})
|
40
42
|
|
41
43
|
Blacklight.onLoad(function () {
|
42
|
-
const elem = document.querySelector('.no-js')
|
44
|
+
const elem = document.querySelector('.no-js');
|
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.
|
48
|
+
if (!elem) return;
|
49
|
+
|
43
50
|
elem.classList.remove('no-js')
|
44
51
|
elem.classList.add('js')
|
45
52
|
})
|
53
|
+
|
54
|
+
window.Blacklight = Blacklight
|
@@ -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)
|
@@ -14,7 +14,7 @@
|
|
14
14
|
<%= render 'sort_and_per_page' %>
|
15
15
|
<%= render partial: 'tools', locals: { document_list: @response.documents } %>
|
16
16
|
<h2 class='section-heading sr-only visually-hidden'><%= t('blacklight.bookmarks.list_title') %></h2>
|
17
|
-
<%= render_document_index %>
|
17
|
+
<%= render_document_index @response.documents %>
|
18
18
|
<%= render 'results_pagination' %>
|
19
19
|
<% end %>
|
20
20
|
</div>
|
@@ -26,7 +26,7 @@
|
|
26
26
|
<%- elsif render_grouped_response? %>
|
27
27
|
<%= Deprecation.silence(Blacklight::RenderPartialsHelperBehavior) { render_grouped_document_index } %>
|
28
28
|
<%- else %>
|
29
|
-
<%= render_document_index %>
|
29
|
+
<%= render_document_index @response.documents %>
|
30
30
|
<%- end %>
|
31
31
|
|
32
32
|
<%= render 'results_pagination' %>
|
data/blacklight.gemspec
CHANGED
@@ -32,7 +32,7 @@ Gem::Specification.new do |s|
|
|
32
32
|
s.add_dependency "deprecation"
|
33
33
|
s.add_dependency "i18n", '>= 1.7.0' # added named parameters
|
34
34
|
s.add_dependency "ostruct", '>= 0.3.2'
|
35
|
-
s.add_dependency "view_component", '~> 2.42
|
35
|
+
s.add_dependency "view_component", '~> 2.42'
|
36
36
|
|
37
37
|
s.add_development_dependency "rsolr", ">= 1.0.6", "< 3" # Library for interacting with rSolr.
|
38
38
|
s.add_development_dependency "rspec-rails", "~> 4.0.0.beta2"
|
@@ -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
|
-
"version": "7.
|
4
|
-
"description": "[![Build Status](https://travis-ci.com/projectblacklight/blacklight.png?branch=
|
3
|
+
"version": "7.21.2",
|
4
|
+
"description": "[![Build Status](https://travis-ci.com/projectblacklight/blacklight.png?branch=main)](https://travis-ci.com/projectblacklight/blacklight) [![Gem Version](https://badge.fury.io/rb/blacklight.png)](http://badge.fury.io/rb/blacklight) [![Coverage Status](https://coveralls.io/repos/github/projectblacklight/blacklight/badge.svg?branch=main)](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.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Rochkind
|
@@ -17,7 +17,7 @@ authors:
|
|
17
17
|
autorequire:
|
18
18
|
bindir: exe
|
19
19
|
cert_chain: []
|
20
|
-
date: 2021-11-
|
20
|
+
date: 2021-11-23 00:00:00.000000000 Z
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
23
23
|
name: rails
|
@@ -129,14 +129,14 @@ dependencies:
|
|
129
129
|
requirements:
|
130
130
|
- - "~>"
|
131
131
|
- !ruby/object:Gem::Version
|
132
|
-
version: 2.42
|
132
|
+
version: '2.42'
|
133
133
|
type: :runtime
|
134
134
|
prerelease: false
|
135
135
|
version_requirements: !ruby/object:Gem::Requirement
|
136
136
|
requirements:
|
137
137
|
- - "~>"
|
138
138
|
- !ruby/object:Gem::Version
|
139
|
-
version: 2.42
|
139
|
+
version: '2.42'
|
140
140
|
- !ruby/object:Gem::Dependency
|
141
141
|
name: rsolr
|
142
142
|
requirement: !ruby/object:Gem::Requirement
|
@@ -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"
|
@@ -933,7 +934,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
933
934
|
- !ruby/object:Gem::Version
|
934
935
|
version: '0'
|
935
936
|
requirements: []
|
936
|
-
rubygems_version: 3.1.
|
937
|
+
rubygems_version: 3.1.4
|
937
938
|
signing_key:
|
938
939
|
specification_version: 4
|
939
940
|
summary: Blacklight provides a discovery interface for any Solr (http://lucene.apache.org/solr)
|