blacklight 7.20.0 → 7.21.2
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 +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": "[](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.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)
|