blacklight-spotlight 3.6.0.beta6 → 3.6.0.beta7

Sign up to get free protection for your applications and to get access to all the features.
@@ -38,7 +38,7 @@ module Spotlight
38
38
 
39
39
  def update_all
40
40
  tags_to_rename = batch_update_params['owned_tags_attributes'].values.select do |tag|
41
- tag[:name]&.present? && tag[:current_name]&.strip != tag[:name]&.strip
41
+ tag[:name].present? && tag[:current_name]&.strip != tag[:name]&.strip
42
42
  end
43
43
 
44
44
  rename_tags_later!(tags_to_rename)
@@ -48,19 +48,24 @@ SirTrevor.Blocks.SolrDocumentsBase = (function(){
48
48
  </div>
49
49
  `},
50
50
 
51
- _itemPanelIiifFields: function(index, data) {
51
+ // Sets the first version of the IIIF information from autocomplete data.
52
+ _itemPanelIiifFields: function(index, autocomplete_data) {
52
53
  return [
53
54
  // '<input type="hidden" name="item[' + index + '][iiif_region]" value="' + (data.iiif_region) + '"/>',
54
55
  // for legacy compatiblity:
55
- '<input type="hidden" name="item[' + index + '][thumbnail_image_url]" value="' + (data.thumbnail_image_url || data.thumbnail || "") + '"/>',
56
- '<input type="hidden" name="item[' + index + '][full_image_url]" value="' + (data.full_image_url || data.thumbnail_image_url || data.thumbnail || "") + '"/>',
57
- '<input type="hidden" name="item[' + index + '][iiif_tilesource]" value="' + (data.iiif_tilesource) + '"/>',
58
- '<input type="hidden" name="item[' + index + '][iiif_manifest_url]" value="' + (data.iiif_manifest_url) + '"/>',
59
- '<input type="hidden" name="item[' + index + '][iiif_canvas_id]" value="' + (data.iiif_canvas_id) + '"/>',
60
- '<input type="hidden" name="item[' + index + '][iiif_image_id]" value="' + (data.iiif_image_id) + '"/>',
56
+ '<input type="hidden" name="item[' + index + '][thumbnail_image_url]" value="' + (autocomplete_data.thumbnail_image_url || autocomplete_data.thumbnail || "") + '"/>',
57
+ '<input type="hidden" name="item[' + index + '][full_image_url]" value="' + (autocomplete_data.full_image_url || autocomplete_data.thumbnail_image_url || autocomplete_data.thumbnail || "") + '"/>',
58
+ '<input type="hidden" name="item[' + index + '][iiif_tilesource]" value="' + (autocomplete_data.iiif_tilesource) + '"/>',
59
+ '<input type="hidden" name="item[' + index + '][iiif_manifest_url]" value="' + (autocomplete_data.iiif_manifest_url) + '"/>',
60
+ '<input type="hidden" name="item[' + index + '][iiif_canvas_id]" value="' + (autocomplete_data.iiif_canvas_id) + '"/>',
61
+ '<input type="hidden" name="item[' + index + '][iiif_image_id]" value="' + (autocomplete_data.iiif_image_id) + '"/>',
61
62
  ].join("\n");
62
63
  },
63
- setIiifFields: function(panel, data, initialize) {
64
+ // Overwrites the hidden inputs from _itemPanelIiifFields with data from the
65
+ // manifest. Called by afterPanelRender - the manifest_data here is built
66
+ // from canvases in the manifest, transformed by spotlight/admin/iiif.js in
67
+ // the #images method.
68
+ setIiifFields: function(panel, manifest_data, initialize) {
64
69
  var legacyThumbnailField = $(panel).find('[name$="[thumbnail_image_url]"]')
65
70
  var legacyFullField = $(panel).find('[name$="[full_image_url]"]')
66
71
 
@@ -70,11 +75,11 @@ SirTrevor.Blocks.SolrDocumentsBase = (function(){
70
75
 
71
76
  legacyThumbnailField.val("");
72
77
  legacyFullField.val("");
73
- $(panel).find('[name$="[iiif_image_id]"]').val(data.imageId);
74
- $(panel).find('[name$="[iiif_tilesource]"]').val(data.tilesource);
75
- $(panel).find('[name$="[iiif_manifest_url]"]').val(data.manifest);
76
- $(panel).find('[name$="[iiif_canvas_id]"]').val(data.canvasId);
77
- $(panel).find('img.img-thumbnail').attr('src', data.thumbnail_image_url || data.tilesource.replace("/info.json", "/full/100,100/0/default.jpg"));
78
+ $(panel).find('[name$="[iiif_image_id]"]').val(manifest_data.imageId);
79
+ $(panel).find('[name$="[iiif_tilesource]"]').val(manifest_data.tilesource);
80
+ $(panel).find('[name$="[iiif_manifest_url]"]').val(manifest_data.manifest);
81
+ $(panel).find('[name$="[iiif_canvas_id]"]').val(manifest_data.canvasId);
82
+ $(panel).find('img.img-thumbnail').attr('src', manifest_data.thumbnail_image_url || manifest_data.tilesource.replace("/info.json", "/full/100,100/0/default.jpg"));
78
83
  },
79
84
  afterPanelRender: function(data, panel) {
80
85
  var context = this;
@@ -31,12 +31,21 @@ module Spotlight
31
31
 
32
32
  solr_params.append_query(query) if query.present?
33
33
 
34
+ # for a browse category formed from a saved search, the query syntax reads as two "must" values
35
+ # e.g. "json"=>{"query"=>{"bool"=>{"must"=>["savedsearchterm", "browsecategorysearchterm"]}}}}
36
+ must_values = solr_params.dig(:json, :query, :bool, :must)
37
+
38
+ return unless must_values&.any?
39
+
40
+ # this type of query must be parsed by lucene to function
41
+ solr_params[:defType] = 'lucene'
42
+
34
43
  # This replicates existing spotlight 2.x search behavior, more or less. It
35
44
  # doesn't take into account the possibility that the browse category query
36
45
  # could use a different search field (which.. doesn't have an existing UI
37
46
  # control.. and may require additional upstream work to properly encapsulate
38
47
  # the two query parameters)
39
- solr_params.dig(:json, :query, :bool, :must)&.map! do |q|
48
+ must_values.map! do |q|
40
49
  q.is_a?(String) ? { edismax: { query: q } } : q
41
50
  end
42
51
  end
@@ -10,15 +10,15 @@ module Spotlight
10
10
  has_paper_trail
11
11
 
12
12
  belongs_to :exhibit, touch: true, optional: true
13
- serialize :facet_fields, Hash
14
- serialize :index_fields, Hash
15
- serialize :search_fields, Hash
16
- serialize :sort_fields, Hash
17
- serialize :default_solr_params, Hash
18
- serialize :show, Hash
19
- serialize :index, Hash
20
- serialize :per_page, Array
21
- serialize :document_index_view_types, Array
13
+ serialize :facet_fields, Hash, coder: YAML
14
+ serialize :index_fields, Hash, coder: YAML
15
+ serialize :search_fields, Hash, coder: YAML
16
+ serialize :sort_fields, Hash, coder: YAML
17
+ serialize :default_solr_params, Hash, coder: YAML
18
+ serialize :show, Hash, coder: YAML
19
+ serialize :index, Hash, coder: YAML
20
+ serialize :per_page, Array, coder: YAML
21
+ serialize :document_index_view_types, Array, coder: YAML
22
22
 
23
23
  include Spotlight::BlacklightConfigurationDefaults
24
24
 
@@ -7,7 +7,7 @@ module Spotlight
7
7
  belongs_to :exhibit, touch: true, optional: true
8
8
  scope :published, -> { where(show_in_sidebar: true) }
9
9
  default_scope { order('weight ASC') }
10
- serialize :contact_info, Hash
10
+ serialize :contact_info, Hash, coder: YAML
11
11
 
12
12
  extend FriendlyId
13
13
  friendly_id :name, use: %i[slugged scoped finders], scope: :exhibit
@@ -8,7 +8,7 @@ module Spotlight
8
8
 
9
9
  attr_accessor :current_exhibit, :name, :email, Spotlight::Engine.config.spambot_honeypot_email_field, :message, :current_url, :request
10
10
 
11
- validates :email, format: { with: /\A([\w.%+\-]+)@([\w\-]+\.)+(\w{2,})\z/i }
11
+ validates :email, format: { with: /\A([\w.%+-]+)@([\w-]+\.)+(\w{2,})\z/i }
12
12
 
13
13
  # the spambot_honeypot_email_field field is intended to be hidden visually from the user,
14
14
  # in hope that a spam bot filling out the form will enter a value, whereas a human with a
@@ -4,7 +4,7 @@ module Spotlight
4
4
  ##
5
5
  # Exhibit custom fields
6
6
  class CustomField < ActiveRecord::Base
7
- serialize :configuration, Hash
7
+ serialize :configuration, Hash, coder: YAML
8
8
  belongs_to :exhibit, optional: true
9
9
 
10
10
  extend FriendlyId
@@ -3,7 +3,7 @@
3
3
  module Spotlight
4
4
  # Exhibit-specific custom search fields
5
5
  class CustomSearchField < ApplicationRecord
6
- serialize :configuration, Hash
6
+ serialize :configuration, Hash, coder: YAML
7
7
  belongs_to :exhibit
8
8
 
9
9
  def label=(label)
@@ -6,7 +6,7 @@ module Spotlight
6
6
  belongs_to :resource, polymorphic: true
7
7
  belongs_to :exhibit, optional: true
8
8
 
9
- serialize :data
9
+ serialize :data, coder: YAML
10
10
 
11
11
  self.inheritance_column = :event_class
12
12
  end
@@ -35,7 +35,7 @@ module Spotlight
35
35
  acts_as_tagger
36
36
  acts_as_taggable
37
37
  delegate :blacklight_config, to: :blacklight_configuration
38
- serialize :facets, Array
38
+ serialize :facets, Array, coder: YAML
39
39
 
40
40
  # NOTE: friendly id associations need to be 'destroy'ed to reap the slug history
41
41
  has_many :about_pages, -> { for_default_locale }, extend: FriendlyId::FinderMethods
@@ -14,7 +14,7 @@ module Spotlight
14
14
  has_many :job_trackers, as: :on, dependent: Rails.version > '6.1' ? :destroy_async : :destroy
15
15
  has_many :subevents, through: :job_trackers, source: :events
16
16
 
17
- serialize :data
17
+ serialize :data, coder: YAML
18
18
 
19
19
  after_initialize do
20
20
  self.data ||= {}
@@ -25,7 +25,7 @@ module Spotlight
25
25
  has_many :solr_document_sidecars
26
26
  has_many :events, as: :resource
27
27
 
28
- serialize :data, Hash
28
+ serialize :data, Hash, coder: YAML
29
29
 
30
30
  ##
31
31
  # Persist the record to the database, and trigger a reindex to solr
@@ -11,8 +11,8 @@ module Spotlight
11
11
  belongs_to :exhibit, optional: false
12
12
  belongs_to :resource, optional: true
13
13
  belongs_to :document, optional: false, polymorphic: true
14
- serialize :data, Hash
15
- serialize :index_status, Hash
14
+ serialize :data, Hash, coder: YAML
15
+ serialize :index_status, Hash, coder: YAML
16
16
 
17
17
  delegate :has_key?, :key?, to: :data
18
18
 
@@ -101,8 +101,10 @@ module Spotlight
101
101
  def convert_stored_value_to_solr(value)
102
102
  if value.blank?
103
103
  nil
104
- elsif value.is_a? Enumerable
104
+ elsif value.is_a? Array
105
105
  value.reject(&:blank?)
106
+ elsif value.is_a? Hash
107
+ value.values.reject(&:blank?)
106
108
  else
107
109
  value
108
110
  end
@@ -56,7 +56,7 @@ module Spotlight
56
56
  # @private
57
57
  # @yield Logger
58
58
  def with_logger
59
- logger = (context&.logger || Rails.logger)
59
+ logger = context&.logger || Rails.logger
60
60
  logger.tagged(pipeline.class) do
61
61
  logger.tagged("#<#{source.class} id=#{source&.id if source.respond_to?(:id)}>") do
62
62
  @logger = logger
@@ -53,7 +53,7 @@ module Spotlight
53
53
  data: [document].to_json,
54
54
  headers: { 'Content-Type' => 'application/json' }
55
55
  rescue StandardError => e
56
- pipeline&.on_error(self, e, document.to_json)
56
+ pipeline&.on_error(e, document.to_json)
57
57
  end
58
58
 
59
59
  def blacklight_solr
@@ -7,7 +7,7 @@ module Spotlight
7
7
  # need to be persisted in order to generate the appropriate content in the invitation email.
8
8
  class InviteUsersService
9
9
  def self.call(resource:)
10
- resource.roles.includes(:user).each do |role|
10
+ resource.roles.includes(:user).find_each do |role|
11
11
  user = role.user
12
12
 
13
13
  user.deliver_invitation if user.created_by_invite? && user.invitation_sent_at.blank?
@@ -23,21 +23,21 @@ module Migration
23
23
  private
24
24
 
25
25
  def migrate_featured_images
26
- Spotlight::FeaturedImage.all.each do |image|
26
+ Spotlight::FeaturedImage.all.find_each do |image|
27
27
  update_iiif_url(image)
28
28
  copy_exhibit_thumbnail_from_featured_image(image)
29
29
  end
30
30
  end
31
31
 
32
32
  def migrate_contact_avatars
33
- Spotlight::Contact.all.each do |contact|
33
+ Spotlight::Contact.all.find_each do |contact|
34
34
  avatar = copy_contact_image_to_avatar(contact)
35
35
  contact.update(avatar: avatar) if avatar
36
36
  end
37
37
  end
38
38
 
39
39
  def migrate_upload_images
40
- Spotlight::Resources::Upload.all.each do |upload|
40
+ Spotlight::Resources::Upload.all.find_each do |upload|
41
41
  copy_upload_to_featured_image(upload)
42
42
  end
43
43
  end
@@ -334,10 +334,23 @@ module Spotlight
334
334
  config.assign_default_roles_to_first_user = true
335
335
 
336
336
  config.exhibit_roles = %w[admin curator viewer]
337
-
338
- if ActiveRecord.respond_to?(:yaml_column_permitted_classes) || ActiveRecord::Base.respond_to?(:yaml_column_permitted_classes)
339
- config.active_record.yaml_column_permitted_classes ||= []
340
- config.active_record.yaml_column_permitted_classes += [Symbol, ActiveSupport::HashWithIndifferentAccess]
337
+ # PaperTrail serializes objects to YAML, so we need to permit these classes to be deserialized
338
+ if ActiveRecord.respond_to?(:yaml_column_permitted_classes)
339
+ # Rails >= 7.0
340
+ ActiveRecord.yaml_column_permitted_classes ||= []
341
+ ActiveRecord.yaml_column_permitted_classes += [Symbol,
342
+ ActiveSupport::HashWithIndifferentAccess,
343
+ ActiveSupport::TimeWithZone,
344
+ ActiveSupport::TimeZone,
345
+ Time]
346
+ elsif ActiveRecord::Base.respond_to?(:yaml_column_permitted_classes)
347
+ # Rails 6.1
348
+ ActiveRecord::Base.yaml_column_permitted_classes ||= []
349
+ ActiveRecord::Base.yaml_column_permitted_classes += [Symbol,
350
+ ActiveSupport::HashWithIndifferentAccess,
351
+ ActiveSupport::TimeWithZone,
352
+ ActiveSupport::TimeZone,
353
+ Time]
341
354
  end
342
355
  end
343
356
  # rubocop:enable Metrics/ClassLength
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Spotlight
4
- VERSION = '3.6.0.beta6'
4
+ VERSION = '3.6.0.beta7'
5
5
  end
@@ -152,7 +152,7 @@ namespace :spotlight do
152
152
  print " OK\n"
153
153
  rescue StandardError => e
154
154
  errors += 1
155
- puts e.to_s
155
+ puts e
156
156
  end
157
157
 
158
158
  exit 1 if errors > 0
@@ -30,4 +30,16 @@ FactoryBot.define do
30
30
 
31
31
  after(:build) { |search| search.thumbnail = FactoryBot.create(:featured_image) }
32
32
  end
33
+
34
+ factory :search_field_search, class: 'Spotlight::Search' do
35
+ exhibit
36
+ title { 'Based on a search field' }
37
+ query_params { { 'search_field' => 'search', 'q' => 'model' } }
38
+ end
39
+
40
+ factory :facet_search, class: 'Spotlight::Search' do
41
+ exhibit
42
+ title { 'Based on a facet' }
43
+ query_params { { 'f' => { 'language_ssim' => 'Latin' } } }
44
+ end
33
45
  end
@@ -60,7 +60,7 @@ module Spotlight
60
60
  EOF
61
61
  click_button('Save changes')
62
62
  # verify that the page was created
63
- expect(page).not_to have_selector('.alert-danger')
63
+ expect(page).to have_no_selector('.alert-danger')
64
64
  expect(page).to have_selector('.alert-info', text: 'page was successfully updated')
65
65
  end
66
66
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blacklight-spotlight
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.0.beta6
4
+ version: 3.6.0.beta7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Beer
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2023-03-15 00:00:00.000000000 Z
14
+ date: 2024-01-30 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: activejob-status
@@ -36,7 +36,7 @@ dependencies:
36
36
  version: '5.0'
37
37
  - - "<"
38
38
  - !ruby/object:Gem::Version
39
- version: '10'
39
+ version: '11'
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
@@ -46,7 +46,7 @@ dependencies:
46
46
  version: '5.0'
47
47
  - - "<"
48
48
  - !ruby/object:Gem::Version
49
- version: '10'
49
+ version: '11'
50
50
  - !ruby/object:Gem::Dependency
51
51
  name: autoprefixer-rails
52
52
  requirement: !ruby/object:Gem::Requirement
@@ -436,7 +436,7 @@ dependencies:
436
436
  version: '11.0'
437
437
  - - "<"
438
438
  - !ruby/object:Gem::Version
439
- version: '13'
439
+ version: '16'
440
440
  type: :runtime
441
441
  prerelease: false
442
442
  version_requirements: !ruby/object:Gem::Requirement
@@ -446,7 +446,7 @@ dependencies:
446
446
  version: '11.0'
447
447
  - - "<"
448
448
  - !ruby/object:Gem::Version
449
- version: '13'
449
+ version: '16'
450
450
  - !ruby/object:Gem::Dependency
451
451
  name: rails
452
452
  requirement: !ruby/object:Gem::Requirement
@@ -809,20 +809,6 @@ dependencies:
809
809
  - - ">="
810
810
  - !ruby/object:Gem::Version
811
811
  version: '0'
812
- - !ruby/object:Gem::Dependency
813
- name: webdrivers
814
- requirement: !ruby/object:Gem::Requirement
815
- requirements:
816
- - - ">="
817
- - !ruby/object:Gem::Version
818
- version: '0'
819
- type: :development
820
- prerelease: false
821
- version_requirements: !ruby/object:Gem::Requirement
822
- requirements:
823
- - - ">="
824
- - !ruby/object:Gem::Version
825
- version: '0'
826
812
  - !ruby/object:Gem::Dependency
827
813
  name: webmock
828
814
  requirement: !ruby/object:Gem::Requirement
@@ -1564,7 +1550,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1564
1550
  - !ruby/object:Gem::Version
1565
1551
  version: 1.3.1
1566
1552
  requirements: []
1567
- rubygems_version: 3.2.32
1553
+ rubygems_version: 3.4.10
1568
1554
  signing_key:
1569
1555
  specification_version: 4
1570
1556
  summary: Enable librarians, curators, and others who are responsible for digital collections