blacklight-spotlight 4.1.2 → 4.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/app/assets/javascripts/spotlight/spotlight.esm.js +146 -27
  4. data/app/assets/javascripts/spotlight/spotlight.esm.js.map +1 -1
  5. data/app/assets/javascripts/spotlight/spotlight.js +146 -27
  6. data/app/assets/javascripts/spotlight/spotlight.js.map +1 -1
  7. data/app/assets/stylesheets/spotlight/_blacklight_configuration.scss +19 -1
  8. data/app/components/spotlight/breadcrumbs_component.html.erb +19 -0
  9. data/app/components/spotlight/breadcrumbs_component.rb +23 -0
  10. data/app/components/spotlight/exhibit_navbar_component.html.erb +25 -0
  11. data/app/components/spotlight/exhibit_navbar_component.rb +12 -0
  12. data/app/components/spotlight/tag_list_form_component.html.erb +14 -0
  13. data/app/components/spotlight/tag_list_form_component.rb +13 -0
  14. data/app/controllers/concerns/spotlight/controller.rb +9 -1
  15. data/app/controllers/concerns/spotlight/search_helper.rb +2 -2
  16. data/app/controllers/spotlight/about_pages_controller.rb +1 -1
  17. data/app/controllers/spotlight/admin_users_controller.rb +2 -2
  18. data/app/controllers/spotlight/appearances_controller.rb +4 -4
  19. data/app/controllers/spotlight/browse_controller.rb +2 -2
  20. data/app/controllers/spotlight/bulk_actions_controller.rb +1 -1
  21. data/app/controllers/spotlight/bulk_updates_controller.rb +7 -2
  22. data/app/controllers/spotlight/catalog_controller.rb +11 -10
  23. data/app/controllers/spotlight/contacts_controller.rb +5 -5
  24. data/app/controllers/spotlight/custom_fields_controller.rb +5 -5
  25. data/app/controllers/spotlight/custom_search_fields_controller.rb +5 -5
  26. data/app/controllers/spotlight/dashboards_controller.rb +4 -4
  27. data/app/controllers/spotlight/exhibits_controller.rb +6 -5
  28. data/app/controllers/spotlight/feature_pages_controller.rb +5 -5
  29. data/app/controllers/spotlight/featured_images_controller.rb +1 -1
  30. data/app/controllers/spotlight/groups_controller.rb +1 -1
  31. data/app/controllers/spotlight/home_pages_controller.rb +2 -2
  32. data/app/controllers/spotlight/job_trackers_controller.rb +3 -3
  33. data/app/controllers/spotlight/metadata_configurations_controller.rb +3 -3
  34. data/app/controllers/spotlight/pages_controller.rb +3 -3
  35. data/app/controllers/spotlight/resources/csv_upload_controller.rb +1 -1
  36. data/app/controllers/spotlight/resources_controller.rb +4 -4
  37. data/app/controllers/spotlight/roles_controller.rb +4 -4
  38. data/app/controllers/spotlight/search_configurations_controller.rb +3 -3
  39. data/app/controllers/spotlight/searches_controller.rb +5 -5
  40. data/app/controllers/spotlight/sites_controller.rb +4 -4
  41. data/app/controllers/spotlight/tags_controller.rb +3 -3
  42. data/app/controllers/spotlight/translations_controller.rb +5 -5
  43. data/app/helpers/spotlight/application_helper.rb +2 -2
  44. data/app/helpers/spotlight/crop_helper.rb +1 -1
  45. data/app/helpers/spotlight/pages_helper.rb +7 -0
  46. data/app/helpers/spotlight/title_helper.rb +2 -2
  47. data/app/javascript/spotlight/admin/blocks/browse_group_categories_block.js +1 -1
  48. data/app/javascript/spotlight/admin/blocks/resources_block.js +82 -1
  49. data/app/javascript/spotlight/admin/blocks/solr_documents_embed_block.js +1 -1
  50. data/app/javascript/spotlight/admin/blocks/uploaded_items_block.js +21 -0
  51. data/app/javascript/spotlight/admin/edit_in_place.js +27 -0
  52. data/app/javascript/spotlight/admin/index.js +0 -2
  53. data/app/javascript/spotlight/admin/sir-trevor/locales.js +11 -0
  54. data/app/jobs/concerns/spotlight/job_tracking.rb +1 -1
  55. data/app/jobs/spotlight/add_tags_job.rb +2 -2
  56. data/app/jobs/spotlight/add_uploads_from_csv.rb +1 -1
  57. data/app/jobs/spotlight/change_visibility_job.rb +2 -2
  58. data/app/jobs/spotlight/process_bulk_updates_csv_job.rb +2 -2
  59. data/app/jobs/spotlight/reindex_exhibit_job.rb +1 -1
  60. data/app/jobs/spotlight/reindex_job.rb +6 -6
  61. data/app/jobs/spotlight/remove_tags_job.rb +2 -2
  62. data/app/jobs/spotlight/rename_tags_job.rb +2 -2
  63. data/app/models/breadcrumb.rb +15 -0
  64. data/app/models/concerns/spotlight/exhibit_defaults.rb +1 -1
  65. data/app/models/concerns/spotlight/exhibit_documents.rb +2 -2
  66. data/app/models/concerns/spotlight/solr_document/finder.rb +4 -4
  67. data/app/models/concerns/spotlight/solr_document.rb +4 -4
  68. data/app/models/concerns/spotlight/translatables.rb +1 -1
  69. data/app/models/spotlight/analytics/ga.rb +3 -3
  70. data/app/models/spotlight/attachment.rb +1 -1
  71. data/app/models/spotlight/background_job_progress.rb +1 -1
  72. data/app/models/spotlight/contact_email.rb +1 -1
  73. data/app/models/spotlight/contact_form.rb +2 -2
  74. data/app/models/spotlight/custom_field.rb +2 -2
  75. data/app/models/spotlight/custom_search_field.rb +2 -2
  76. data/app/models/spotlight/job_tracker.rb +1 -1
  77. data/app/models/spotlight/page.rb +2 -2
  78. data/app/models/spotlight/resources/iiif_service.rb +4 -4
  79. data/app/models/spotlight/role.rb +1 -1
  80. data/app/models/spotlight/search.rb +2 -2
  81. data/app/services/spotlight/bulk_updates_csv_template_service.rb +2 -2
  82. data/app/services/spotlight/clone_translated_page_from_locale.rb +1 -1
  83. data/app/services/spotlight/etl/pipeline.rb +1 -1
  84. data/app/views/shared/_exhibit_navbar.html.erb +2 -24
  85. data/app/views/shared/_masthead.html.erb +1 -1
  86. data/app/views/spotlight/exhibits/_form.html.erb +1 -1
  87. data/app/views/spotlight/exhibits/_new_exhibit_form.html.erb +1 -1
  88. data/app/views/spotlight/metadata_configurations/_metadata_field.html.erb +16 -5
  89. data/app/views/spotlight/metadata_configurations/edit.html.erb +2 -2
  90. data/app/views/spotlight/sir_trevor/blocks/_solr_documents_block.html.erb +3 -3
  91. data/app/views/spotlight/sir_trevor/blocks/_solr_documents_carousel_block.html.erb +3 -3
  92. data/app/views/spotlight/sir_trevor/blocks/_solr_documents_features_block.html.erb +3 -3
  93. data/app/views/spotlight/sir_trevor/blocks/_solr_documents_grid_block.html.erb +3 -3
  94. data/app/views/spotlight/sir_trevor/blocks/_uploaded_items_block.html.erb +3 -2
  95. data/config/locales/spotlight.en.yml +4 -0
  96. data/lib/generators/spotlight/templates/catalog_controller.rb +1 -0
  97. data/lib/generators/spotlight/templates/config/initializers/spotlight_initializer.rb +4 -0
  98. data/lib/migration/iiif.rb +3 -3
  99. data/lib/spotlight/engine.rb +6 -26
  100. data/lib/spotlight/version.rb +1 -1
  101. data/lib/tasks/spotlight_tasks.rake +3 -3
  102. data/spec/factories/exhibits.rb +1 -1
  103. data/spec/support/views/test_view_helpers.rb +0 -1
  104. metadata +11 -27
  105. data/app/builders/spotlight/bootstrap_breadcrumbs_builder.rb +0 -39
  106. data/app/javascript/spotlight/admin/appearance.js +0 -22
  107. data/app/views/shared/_breadcrumbs.html.erb +0 -7
@@ -8,7 +8,7 @@ module Spotlight
8
8
  # filtered by the exhibit-specific solr field.
9
9
  #
10
10
  # @return [Enumerable<SolrDocument>]
11
- def solr_documents(&block)
11
+ def solr_documents(&)
12
12
  return to_enum(:solr_documents) unless block_given?
13
13
 
14
14
  start = 0
@@ -17,7 +17,7 @@ module Spotlight
17
17
  response = repository.search(search_params.start(start).to_h)
18
18
 
19
19
  while response.documents.present?
20
- response.documents.each(&block)
20
+ response.documents.each(&)
21
21
  start += response.documents.length
22
22
  response = repository.search(search_params.start(start).to_h)
23
23
  end
@@ -19,17 +19,17 @@ module Spotlight
19
19
  @index ||= blacklight_config.repository_class.new(blacklight_config)
20
20
  end
21
21
 
22
- def find_each(&block)
22
+ def find_each(&)
23
23
  return to_enum(:find_each) unless block_given?
24
24
 
25
25
  start = 0
26
26
  search_params = { q: '*:*', fl: 'id', facet: false }
27
- response = index.search(search_params.merge(start: start))
27
+ response = index.search(search_params.merge(start:))
28
28
 
29
29
  while response.documents.present?
30
- response.documents.each(&block)
30
+ response.documents.each(&)
31
31
  start += response.documents.length
32
- response = index.search(search_params.merge(start: start))
32
+ response = index.search(search_params.merge(start:))
33
33
  end
34
34
  end
35
35
 
@@ -87,7 +87,7 @@ module Spotlight
87
87
  end
88
88
 
89
89
  def sidecar(exhibit)
90
- sidecars.find_or_initialize_by exhibit: exhibit, document_id: id, document_type: self.class.to_s
90
+ sidecars.find_or_initialize_by exhibit:, document_id: id, document_type: self.class.to_s
91
91
  end
92
92
 
93
93
  def to_solr
@@ -156,12 +156,12 @@ module Spotlight
156
156
  deep_compact(attributes)
157
157
  end
158
158
 
159
- def deep_transform_values(object, &block)
159
+ def deep_transform_values(object, &)
160
160
  # Available in Rails 6
161
161
  if object.respond_to?(:deep_transform_values)
162
- object.deep_transform_values(&block)
162
+ object.deep_transform_values(&)
163
163
  else
164
- _deep_transform_values(object, &block)
164
+ _deep_transform_values(object, &)
165
165
  end
166
166
  end
167
167
 
@@ -32,7 +32,7 @@ module Spotlight
32
32
  define_method(:"translated_#{attr_name}") do |default: [], **options|
33
33
  default = Array.wrap(default)
34
34
  default.prepend(attr_translation(attr_name)) if I18n.locale == I18n.default_locale
35
- I18n.t(attr_name, scope: slug, default: default, **options).presence
35
+ I18n.t(attr_name, scope: slug, default:, **options).presence
36
36
  end
37
37
  end
38
38
  end
@@ -37,8 +37,8 @@ module Spotlight
37
37
  filter: Google::Analytics::Data::V1beta::Filter.new(
38
38
  field_name: 'pagePath',
39
39
  string_filter: Google::Analytics::Data::V1beta::Filter::StringFilter.new(
40
- match_type: :BEGINS_WITH,
41
- value: path.to_s
40
+ match_type: :PARTIAL_REGEXP,
41
+ value: "^#{path}(/.*)?$"
42
42
  )
43
43
  )
44
44
  )
@@ -115,7 +115,7 @@ module Spotlight
115
115
 
116
116
  @report_data = report_data
117
117
 
118
- OpenStruct.new({ rows: rows, totals: totals })
118
+ OpenStruct.new({ rows:, totals: })
119
119
  end
120
120
 
121
121
  private
@@ -8,7 +8,7 @@ module Spotlight
8
8
  mount_uploader :file, Spotlight::AttachmentUploader
9
9
 
10
10
  def as_json(options = nil)
11
- file.as_json(options).merge(name: name, uid: uid, attachment: to_global_id)
11
+ file.as_json(options).merge(name:, uid:, attachment: to_global_id)
12
12
  end
13
13
  end
14
14
  end
@@ -20,7 +20,7 @@ module Spotlight
20
20
  finished_at: localized_finish_time,
21
21
  updated_at: localized_updated_time,
22
22
  total: [total, completed].max,
23
- completed: completed,
23
+ completed:,
24
24
  finished: finished?,
25
25
  errored: errored?
26
26
  }
@@ -33,7 +33,7 @@ module Spotlight
33
33
  end
34
34
 
35
35
  def send_devise_notification(notification, *args)
36
- notice = notification_mailer.send(notification, self, *args, exhibit: exhibit)
36
+ notice = notification_mailer.send(notification, self, *args, exhibit:)
37
37
  if notice.respond_to? :deliver_now
38
38
  notice.deliver_now
39
39
  else
@@ -19,8 +19,8 @@ module Spotlight
19
19
 
20
20
  def headers
21
21
  {
22
- to: to,
23
- subject: I18n.t(:'spotlight.contact_form.subject', application_name: application_name),
22
+ to:,
23
+ subject: I18n.t(:'spotlight.contact_form.subject', application_name:),
24
24
  cc: contact_emails.join(', ')
25
25
  }
26
26
  end
@@ -34,7 +34,7 @@ module Spotlight
34
34
  end
35
35
 
36
36
  def label
37
- conf = if field && blacklight_configuration && blacklight_configuration.index_fields.key?(field)
37
+ conf = if field && blacklight_configuration&.index_fields&.key?(field)
38
38
  blacklight_configuration.index_fields[field].reverse_merge(configuration)
39
39
  else
40
40
  configuration
@@ -74,7 +74,7 @@ module Spotlight
74
74
  end
75
75
 
76
76
  def update_blacklight_configuration_label(label)
77
- return unless field && blacklight_configuration && blacklight_configuration.index_fields.key?(field)
77
+ return unless field && blacklight_configuration&.index_fields&.key?(field)
78
78
 
79
79
  blacklight_configuration.index_fields[field]['label'] = label
80
80
  blacklight_configuration.save
@@ -17,7 +17,7 @@ module Spotlight
17
17
  end
18
18
 
19
19
  def label
20
- conf = if slug && blacklight_configuration && blacklight_configuration.search_fields.key?(slug)
20
+ conf = if slug && blacklight_configuration&.search_fields&.key?(slug)
21
21
  blacklight_configuration.search_fields[slug].reverse_merge(configuration)
22
22
  else
23
23
  configuration
@@ -32,7 +32,7 @@ module Spotlight
32
32
  end
33
33
 
34
34
  def update_blacklight_configuration_label(label)
35
- return unless slug && blacklight_configuration && blacklight_configuration.search_fields.key?(slug)
35
+ return unless slug && blacklight_configuration&.search_fields&.key?(slug)
36
36
 
37
37
  blacklight_configuration.search_fields[slug]['label'] = label
38
38
  blacklight_configuration.save
@@ -92,7 +92,7 @@ module Spotlight
92
92
  end
93
93
 
94
94
  def append_log_entry(type:, exhibit: nil, **args)
95
- events.create(type: type, exhibit: exhibit, data: args)
95
+ events.create(type:, exhibit:, data: args)
96
96
  rescue StandardError => e
97
97
  Rails.logger.error("Unable to create log entry for job tracker #{id}: #{e}")
98
98
  end
@@ -31,7 +31,7 @@ module Spotlight
31
31
  scope :at_top_level, -> { where(parent_page_id: nil) }
32
32
  scope :published, -> { where(published: true) }
33
33
  scope :recent, -> { order('updated_at DESC').limit(10) }
34
- scope :for_locale, ->(locale = I18n.locale) { unscope(where: :locale).where(locale: locale) }
34
+ scope :for_locale, ->(locale = I18n.locale) { unscope(where: :locale).where(locale:) }
35
35
  scope :for_default_locale, -> { for_locale(I18n.default_locale) }
36
36
 
37
37
  has_one :lock, as: :on, dependent: :destroy
@@ -171,7 +171,7 @@ module Spotlight
171
171
  end
172
172
  end
173
173
 
174
- translated_pages.update(weight: weight) if saved_change_to_weight?
174
+ translated_pages.update(weight:) if saved_change_to_weight?
175
175
  end
176
176
  end
177
177
  end
@@ -56,21 +56,21 @@ module Spotlight
56
56
 
57
57
  private
58
58
 
59
- def recursive_manifests(thing, &block)
59
+ def recursive_manifests(thing, &)
60
60
  return to_enum(:recursive_manifests, thing) unless block_given?
61
61
 
62
- thing.manifests.each(&block)
62
+ thing.manifests.each(&)
63
63
 
64
64
  return if thing.collections.blank?
65
65
 
66
66
  thing.collections.each do |collection|
67
- recursive_manifests(collection, &block)
67
+ recursive_manifests(collection, &)
68
68
  end
69
69
  end
70
70
  end
71
71
 
72
72
  def create_iiif_manifest(manifest, collection = nil)
73
- IiifManifest.new(url: manifest['@id'], manifest: manifest, collection: collection)
73
+ IiifManifest.new(url: manifest['@id'], manifest:, collection:)
74
74
  end
75
75
 
76
76
  def manifest?
@@ -32,7 +32,7 @@ module Spotlight
32
32
  # validates :user, uniqueness: { scope: :exhibit}
33
33
  # but it puts the error message on the user_key instead of user so that the form will render correctly
34
34
  def user_must_be_unique
35
- errors.add(:user_key, 'already a member of this exhibit') if Spotlight::Role.where(resource: resource, user: user).where.not(id: id).any?
35
+ errors.add(:user_key, 'already a member of this exhibit') if Spotlight::Role.where(resource:, user:).where.not(id:).any?
36
36
  end
37
37
  end
38
38
  end
@@ -49,14 +49,14 @@ module Spotlight
49
49
  thumbnail.iiif_url
50
50
  end
51
51
 
52
- def documents(&block)
52
+ def documents(&)
53
53
  start = 0
54
54
  response = repository.search(search_params.start(start))
55
55
 
56
56
  return to_enum(:documents) { response['response']['numFound'] } unless block_given?
57
57
 
58
58
  while response.documents.present?
59
- response.documents.each(&block)
59
+ response.documents.each(&)
60
60
  start += response.documents.length
61
61
  response = repository.search(search_params.start(start))
62
62
  end
@@ -12,9 +12,9 @@ module Spotlight
12
12
  end
13
13
 
14
14
  def template(view_context:, title: true, tags: true, visibility: true)
15
- return to_enum(:template, view_context: view_context, title: title, tags: tags, visibility: visibility) unless block_given?
15
+ return to_enum(:template, view_context:, title:, tags:, visibility:) unless block_given?
16
16
 
17
- yield ::CSV.generate_line(csv_headers(title: title, tags: tags, visibility: visibility))
17
+ yield ::CSV.generate_line(csv_headers(title:, tags:, visibility:))
18
18
  each_document do |document|
19
19
  sidecar = document.sidecar(exhibit)
20
20
  yield ::CSV.generate_line([
@@ -13,7 +13,7 @@ module Spotlight
13
13
  end
14
14
 
15
15
  def self.call(locale:, page:)
16
- new(locale: locale, page: page).clone
16
+ new(locale:, page:).clone
17
17
  end
18
18
 
19
19
  def clone
@@ -59,7 +59,7 @@ module Spotlight
59
59
  # @yield (optioanlly..) each transformed document after it is transformed but before
60
60
  # it is sent to the loaders
61
61
  def call(context, data: {}, cache: nil, &block)
62
- executor(context, cache: cache).call(data: data, &block)
62
+ executor(context, cache:).call(data:, &block)
63
63
  end
64
64
 
65
65
  ##
@@ -1,24 +1,2 @@
1
- <div id="exhibit-navbar" class="exhibit-navbar navbar navbar-light navbar-expand-md" role="navigation" aria-label="<%= t('spotlight.exhibitnavbar.label') %>">
2
- <div class="container flex-column flex-md-row">
3
- <% if resource_masthead? %>
4
- <%= link_to(current_exhibit.title, spotlight.exhibit_path(current_exhibit), class: 'navbar-brand') %>
5
- <% end %>
6
-
7
- <ul class="navbar-nav <%= resource_masthead? ? 'justify-content-md-end' : 'mr-auto me-auto' %>">
8
- <li class="nav-item <%= "active" if current_page?([spotlight, current_exhibit]) %>"><%= link_to t(:'spotlight.curation.nav.home'), [spotlight, current_exhibit], class: 'nav-link' %></li>
9
- <% current_exhibit.main_navigations.displayable.each do |navigation| %>
10
- <%= render partial: "shared/#{navigation.nav_type}_navbar", locals: { navigation: navigation } %>
11
- <% end %>
12
- </ul>
13
- <% if should_render_spotlight_search_bar? %>
14
- <div class="navbar-right navbar-nav exhibit-search-form mt-3 mt-md-0">
15
- <%= render Blacklight::SearchBarComponent.new(
16
- url: search_action_url,
17
- advanced_search_url: search_action_url(action: 'advanced_search'),
18
- params: search_state.params_for_search.except(:qt),
19
- autocomplete_path: suggest_index_catalog_path
20
- ) %>
21
- </div>
22
- <% end %>
23
- </div>
24
- </div>
1
+ <%- Spotlight.deprecator.warn("_exhibit_navbar.html.erb will be removed. Customize the exhibit navbar using components instead.") if !blacklight_config.key?(:exhibit_navbar_component) %>
2
+ <%= render (blacklight_config&.exhibit_navbar_component || Spotlight::ExhibitNavbarComponent).new %>
@@ -42,4 +42,4 @@
42
42
  <%= masthead_navbar unless resource_masthead? %>
43
43
  </header>
44
44
 
45
- <%= render 'shared/breadcrumbs' unless resource_masthead? %>
45
+ <%= render Spotlight::BreadcrumbsComponent.new(breadcrumbs:) %>
@@ -3,7 +3,7 @@
3
3
  <%= f.text_field :title, disabled: !default_language?, help: !default_language? ? t('.uneditable_non_default_language') : '' %>
4
4
  <%= f.text_field :subtitle %>
5
5
  <%= f.text_area :description %>
6
- <%= f.text_field :tag_list, value: f.object.tag_list.to_s %>
6
+ <%= render Spotlight::TagListFormComponent.new(form: f) %>
7
7
  <%= f.form_group(:contact_emails, label: { text: nil, class: nil, for: 'exhibit_contact_email_0' }, class: 'form-group mb-3', help: nil) do %>
8
8
  <%= f.fields_for :contact_emails do |contact| %>
9
9
  <%= render partial: 'contact', locals: {exhibit: @exhibit, contact: contact} %>
@@ -1,7 +1,7 @@
1
1
  <%= bootstrap_form_for @exhibit, url: ((spotlight.exhibit_path(@exhibit) if @exhibit.persisted?) || spotlight.exhibits_path), layout: :horizontal, label_col: 'col-md-2', control_col: 'col-md-10' do |f| %>
2
2
  <%= f.text_field :title, label: t(:'.fields.title.label'), help: t(:'.fields.title.help_block') %>
3
3
  <%= f.text_field :slug, label: t(:'.fields.slug.label'), help: t(:'.fields.slug.help_block') %>
4
- <%= f.text_field :tag_list %>
4
+ <%= render Spotlight::TagListFormComponent.new(form: f) %>
5
5
 
6
6
  <%= render 'initial_resources_form', locals: { f: f } %>
7
7
 
@@ -1,12 +1,23 @@
1
- <tr data-id="<%= key.parameterize %>" class="dd-item">
1
+ <% default_field_label = local_assigns.dig(:config, :original, :label) %>
2
+
3
+ <tr data-id="<%= key.parameterize %>" class="dd-item" data-behavior="restore-default">
2
4
  <%= f.fields_for key do |field| %>
3
5
  <td>
4
6
  <%= field.hidden_field :weight, 'data-property' => 'weight' %>
5
- <div class="handle-wrap" data-in-place-edit-target=".edit-in-place" data-in-place-edit-field-target="[data-edit-field-target='true']">
7
+ <div class="handle-wrap d-flex">
6
8
  <div class="dd-handle dd3-handle"><%= t :drag %></div>
7
- <a href="#edit-in-place" class="field-label edit-in-place"><%= config.display_label %></a>
8
- <%= field.hidden_field :label, value: config.display_label, class: 'form-control form-control-sm', data: {:"edit-field-target" => 'true'} %>
9
- </div>
9
+ <div class="flex-grow-1 align-self-center">
10
+ <span data-in-place-edit-target=".edit-in-place" data-in-place-edit-field-target="[data-edit-field-target='true']">
11
+ <a href="#edit-in-place" class="field-label edit-in-place align-self-center"><%= config.display_label %></a>
12
+ <%= field.hidden_field :label, value: config.display_label, class: 'metadata-label-edit form-control form-control-sm', data: {:"edit-field-target" => 'true', default_value: default_field_label} %>
13
+ </span>
14
+ </div>
15
+ <% if default_field_label %>
16
+ <div class="restore-default">
17
+ <%= button_tag t(:'.restore_default'), data: {:"restore-default" => true}, class: "btn btn-secondary btn-sm #{'d-none' if config.display_label == default_field_label}" %>
18
+ </div>
19
+ <% end %>
20
+ </div>
10
21
  </td>
11
22
  <td class="checkbox-cell text-center">
12
23
  <%= field.check_box_without_bootstrap :show, checked: config.show, disabled: !config.immutable.show.nil?, hide_label: true %>
@@ -8,10 +8,10 @@
8
8
 
9
9
  <p class="instructions"><%= t :'.instructions' %></p>
10
10
 
11
- <table id="nested-fields" class="table table-striped dd-table">
11
+ <table id="nested-fields" class="metadata-configuration table table-striped dd-table">
12
12
  <thead>
13
13
  <tr>
14
- <th><%= t :'.field.label' %></th>
14
+ <th class="w-50"><%= t :'.field.label' %></th>
15
15
  <th class="text-center">
16
16
  <div>
17
17
  <%= t :'.view.show' %>
@@ -9,11 +9,11 @@
9
9
  <div class="box" data-id="<%= document.id %>">
10
10
  <div class="contents">
11
11
  <% if block_options[:thumbnail_image_url].present? %>
12
- <%= link_to_document(document, image_tag(block_options[:thumbnail_image_url], class: 'img-thumbnail', alt: doc_presenter.heading, skip_pipeline: true), counter: -1) %>
12
+ <%= link_to_document(document, image_tag(block_options[:thumbnail_image_url], class: 'img-thumbnail', alt: resource_alt_text(block_options, doc_presenter.heading), skip_pipeline: true), counter: -1) %>
13
13
  <% elsif block_options[:iiif_tilesource_base].present? %>
14
- <%= link_to_document(document, image_tag(block_options[:iiif_tilesource_base] + '/full/!400,400/0/default.jpg', class: 'img-thumbnail', alt: doc_presenter.heading, skip_pipeline: true), counter: -1) %>
14
+ <%= link_to_document(document, image_tag(block_options[:iiif_tilesource_base] + '/full/!400,400/0/default.jpg', class: 'img-thumbnail', alt: resource_alt_text(block_options, doc_presenter.heading), skip_pipeline: true), counter: -1) %>
15
15
  <% elsif doc_presenter.thumbnail.exists? %>
16
- <%= doc_presenter.thumbnail.thumbnail_tag({ class: 'img-thumbnail', alt: doc_presenter.heading }, document_counter: -1) %>
16
+ <%= doc_presenter.thumbnail.thumbnail_tag({ class: 'img-thumbnail', alt: resource_alt_text(block_options, doc_presenter.heading) }, document_counter: -1) %>
17
17
  <% end %>
18
18
  <% if solr_documents_block.primary_caption? %>
19
19
  <div class="caption primary-caption">
@@ -9,11 +9,11 @@
9
9
  <% doc_presenter = document_presenter(document) %>
10
10
  <div class="carousel-item <%= 'active' if index == 0 %>" data-id="<%= document.id %>">
11
11
  <% if block_options[:full_image_url].present? %>
12
- <%= link_to_document(document, image_tag(block_options[:full_image_url], alt: doc_presenter.heading, skip_pipeline: true), counter: -1) %>
12
+ <%= link_to_document(document, image_tag(block_options[:full_image_url], alt: resource_alt_text(block_options, doc_presenter.heading), skip_pipeline: true), counter: -1) %>
13
13
  <% elsif block_options[:iiif_tilesource_base].present? %>
14
- <%= link_to_document(document, image_tag(block_options[:iiif_tilesource_base] + '/full/!800,800/0/default.jpg', alt: doc_presenter.heading, skip_pipeline: true), counter: -1) %>
14
+ <%= link_to_document(document, image_tag(block_options[:iiif_tilesource_base] + '/full/!800,800/0/default.jpg', alt: resource_alt_text(block_options, doc_presenter.heading), skip_pipeline: true), counter: -1) %>
15
15
  <% elsif doc_presenter.thumbnail.exists? %>
16
- <%= doc_presenter.thumbnail.thumbnail_tag({ alt: doc_presenter.heading }, document_counter: -1) %>
16
+ <%= doc_presenter.thumbnail.thumbnail_tag({ alt: resource_alt_text(block_options, doc_presenter.heading) }, document_counter: -1) %>
17
17
  <% end %>
18
18
  <div class="carousel-caption">
19
19
  <% if solr_documents_carousel_block.primary_caption? %>
@@ -12,11 +12,11 @@
12
12
  <% doc_presenter = document_presenter(document) %>
13
13
  <div class="carousel-item <%= 'active' if index == 0 %>" data-id="<%= document.id %>">
14
14
  <% if block_options[:full_image_url].present? %>
15
- <%= link_to_document(document, image_tag(block_options[:full_image_url], alt: doc_presenter.heading, skip_pipeline: true), counter: -1) %>
15
+ <%= link_to_document(document, image_tag(block_options[:full_image_url], alt: resource_alt_text(block_options, doc_presenter.heading), skip_pipeline: true), counter: -1) %>
16
16
  <% elsif block_options[:iiif_tilesource_base].present? %>
17
- <%= link_to_document(document, image_tag(block_options[:iiif_tilesource_base] + '/full/!800,800/0/default.jpg', alt: doc_presenter.heading, skip_pipeline: true), counter: -1) %>
17
+ <%= link_to_document(document, image_tag(block_options[:iiif_tilesource_base] + '/full/!800,800/0/default.jpg', alt: resource_alt_text(block_options, doc_presenter.heading), skip_pipeline: true), counter: -1) %>
18
18
  <% elsif doc_presenter.thumbnail.exists? %>
19
- <%= doc_presenter.thumbnail.thumbnail_tag({ alt: doc_presenter.heading }, document_counter: -1) %>
19
+ <%= doc_presenter.thumbnail.thumbnail_tag({ alt: resource_alt_text(block_options, doc_presenter.heading) }, document_counter: -1) %>
20
20
  <% end %>
21
21
  </div>
22
22
 
@@ -6,11 +6,11 @@
6
6
  <% doc_presenter = document_presenter(document) %>
7
7
  <div class="box item-<%= index %>" data-id="<%= document.id %>">
8
8
  <% if block_options[:thumbnail_image_url].present? %>
9
- <%= link_to_document(document, image_tag(block_options[:thumbnail_image_url], class: 'img-thumbnail', alt: doc_presenter.heading, skip_pipeline: true), counter: -1) %>
9
+ <%= link_to_document(document, image_tag(block_options[:thumbnail_image_url], class: 'img-thumbnail', alt: resource_alt_text(block_options, doc_presenter.heading), skip_pipeline: true), counter: -1) %>
10
10
  <% elsif block_options[:iiif_tilesource_base].present? %>
11
- <%= link_to_document(document, image_tag(block_options[:iiif_tilesource_base] + '/full/!400,400/0/default.jpg', class: 'img-thumbnail', alt: doc_presenter.heading, skip_pipeline: true), counter: -1) %>
11
+ <%= link_to_document(document, image_tag(block_options[:iiif_tilesource_base] + '/full/!400,400/0/default.jpg', class: 'img-thumbnail', alt: resource_alt_text(block_options, doc_presenter.heading), skip_pipeline: true), counter: -1) %>
12
12
  <% elsif doc_presenter.thumbnail.exists? %>
13
- <%= doc_presenter.thumbnail.thumbnail_tag({ class: 'img-thumbnail', alt: doc_presenter.heading }, document_counter: -1) %>
13
+ <%= doc_presenter.thumbnail.thumbnail_tag({ class: 'img-thumbnail', alt: resource_alt_text(block_options, doc_presenter.heading) }, document_counter: -1) %>
14
14
  <% end %>
15
15
  </div>
16
16
  <% end %>
@@ -6,10 +6,11 @@
6
6
  <div class="contents">
7
7
  <% if file[:link].present? %>
8
8
  <%= link_to file[:link], rel: 'ugc' do %>
9
- <%= image_tag file[:url], class: 'img-thumbnail', alt: file[:caption] %>
9
+ <%= image_tag file[:url], class: 'img-thumbnail', alt: resource_alt_text(file, file[:caption]) %>
10
10
  <% end %>
11
11
  <% else %>
12
- <%= image_tag file[:url], class: 'img-thumbnail', alt: '', role: 'presentation' %>
12
+ <% alt_text = resource_alt_text(file, '') %>
13
+ <%= image_tag file[:url], class: 'img-thumbnail', alt: alt_text, role: alt_text.present? ? nil : 'presentation' %>
13
14
  <% end %>
14
15
  <% if file[:caption].present? %>
15
16
  <div class="caption">
@@ -707,6 +707,8 @@ en:
707
707
  select_all: Select all
708
708
  view:
709
709
  show: Item details
710
+ metadata_field:
711
+ restore_default: Restore default
710
712
  pages:
711
713
  edit:
712
714
  header: Edit page
@@ -721,6 +723,8 @@ en:
721
723
  index:
722
724
  about_pages:
723
725
  header: About pages
726
+ bulk_updates:
727
+ header: Bulk updates
724
728
  feature_pages:
725
729
  header: Feature pages
726
730
  home_pages_header: Homepage
@@ -16,6 +16,7 @@ class CatalogController < ApplicationController
16
16
  # Blacklight 8 sets a default value to 'advanced'
17
17
  config.json_solr_path = nil
18
18
  config.header_component = Spotlight::HeaderComponent
19
+ config.exhibit_navbar_component = Spotlight::ExhibitNavbarComponent
19
20
  config.document_solr_path = 'get'
20
21
  config.document_unique_id_param = 'ids'
21
22
 
@@ -83,6 +83,10 @@
83
83
  # Spotlight::Engine.config.ga_debug_mode = false
84
84
  # end
85
85
 
86
+ # ==> Customizable settings for site tags
87
+ # When set the free text tag list field becomes multiple selection checklist
88
+ # Spotlight::Engine.config.site_tags = []
89
+
86
90
  # ==> Sir Trevor Widget Configuration
87
91
  # These are set by default by Spotlight's configuration,
88
92
  # but you can customize them here, or in the SirTrevorRails::Block#custom_block_types method
@@ -32,7 +32,7 @@ module Migration
32
32
  def migrate_contact_avatars
33
33
  Spotlight::Contact.all.find_each do |contact|
34
34
  avatar = copy_contact_image_to_avatar(contact)
35
- contact.update(avatar: avatar) if avatar
35
+ contact.update(avatar:) if avatar
36
36
  end
37
37
  end
38
38
 
@@ -70,7 +70,7 @@ module Migration
70
70
  old_file = File.new(filepath)
71
71
  image = contact.create_avatar { |i| i.image.store!(old_file) }
72
72
  iiif_tilesource = Spotlight::Engine.config.iiif_service.info_url(image)
73
- image.update(iiif_tilesource: iiif_tilesource, iiif_region: avatar_coordinates(contact))
73
+ image.update(iiif_tilesource:, iiif_region: avatar_coordinates(contact))
74
74
  image
75
75
  end
76
76
 
@@ -84,7 +84,7 @@ module Migration
84
84
  old_file = File.new(filepath)
85
85
  image = upload.create_upload { |i| i.image.store!(old_file) }
86
86
  iiif_tilesource = Spotlight::Engine.config.iiif_service.info_url(image)
87
- image.update(iiif_tilesource: iiif_tilesource)
87
+ image.update(iiif_tilesource:)
88
88
  upload.upload_id = image.id
89
89
  upload.save_and_index
90
90
  end
@@ -27,15 +27,6 @@ module Spotlight
27
27
  # rubocop:disable Metrics/ClassLength
28
28
  class Engine < ::Rails::Engine
29
29
  isolate_namespace Spotlight
30
- # Breadcrumbs on rails must be required outside of an initializer or it doesn't get loaded.
31
- require 'breadcrumbs_on_rails/breadcrumbs'
32
- require 'breadcrumbs_on_rails/action_controller'
33
-
34
- initializer 'breadcrumbs_on_rails.initialize' do
35
- ActiveSupport.on_load(:action_controller) do
36
- include BreadcrumbsOnRails::ActionController
37
- end
38
- end
39
30
 
40
31
  require 'carrierwave'
41
32
  require 'redcarpet' # required for markdown support in github/markup https://github.com/github/markup#markups
@@ -145,6 +136,8 @@ module Spotlight
145
136
  config.full_image_field = :full_image_url_ssm
146
137
  config.thumbnail_field = :thumbnail_url_ssm
147
138
 
139
+ Spotlight::Engine.config.site_tags = nil
140
+
148
141
  # Defaults to the blacklight_config.index.title_field:
149
142
  config.upload_title_field = nil # UploadFieldConfig.new(...)
150
143
  config.upload_description_field = :spotlight_upload_description_tesim
@@ -337,23 +330,10 @@ module Spotlight
337
330
 
338
331
  config.exhibit_roles = %w[admin curator viewer]
339
332
  # PaperTrail serializes objects to YAML, so we need to permit these classes to be deserialized
340
- if ActiveRecord.respond_to?(:yaml_column_permitted_classes)
341
- # Rails >= 7.0
342
- ActiveRecord.yaml_column_permitted_classes ||= []
343
- ActiveRecord.yaml_column_permitted_classes += [Symbol,
344
- ActiveSupport::HashWithIndifferentAccess,
345
- ActiveSupport::TimeWithZone,
346
- ActiveSupport::TimeZone,
347
- Time]
348
- elsif ActiveRecord::Base.respond_to?(:yaml_column_permitted_classes)
349
- # Rails 6.1
350
- ActiveRecord::Base.yaml_column_permitted_classes ||= []
351
- ActiveRecord::Base.yaml_column_permitted_classes += [Symbol,
352
- ActiveSupport::HashWithIndifferentAccess,
353
- ActiveSupport::TimeWithZone,
354
- ActiveSupport::TimeZone,
355
- Time]
356
- end
333
+ ActiveRecord.yaml_column_permitted_classes += [ActiveSupport::HashWithIndifferentAccess,
334
+ ActiveSupport::TimeWithZone,
335
+ ActiveSupport::TimeZone,
336
+ Time]
357
337
  end
358
338
  # rubocop:enable Metrics/ClassLength
359
339
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Spotlight
4
- VERSION = '4.1.2'
4
+ VERSION = '4.3.0'
5
5
  end