blacklight-spotlight 5.1.0 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +153 -48
  3. data/app/assets/javascripts/spotlight/spotlight.esm.js +33 -1
  4. data/app/assets/javascripts/spotlight/spotlight.esm.js.map +1 -1
  5. data/app/assets/javascripts/spotlight/spotlight.js +33 -1
  6. data/app/assets/javascripts/spotlight/spotlight.js.map +1 -1
  7. data/app/assets/stylesheets/spotlight/_admin_users.scss +28 -0
  8. data/app/assets/stylesheets/spotlight/_browse.scss +1 -1
  9. data/app/assets/stylesheets/spotlight/_featured_browse_categories_block.scss +1 -1
  10. data/app/assets/stylesheets/spotlight/_spotlight.scss +1 -0
  11. data/app/components/spotlight/admin_users/email_component.html.erb +5 -0
  12. data/app/components/spotlight/admin_users/email_component.rb +22 -0
  13. data/app/components/spotlight/admin_users/exhibit_roles_component.html.erb +28 -0
  14. data/app/components/spotlight/admin_users/exhibit_roles_component.rb +19 -0
  15. data/app/components/spotlight/admin_users/site_admin_component.html.erb +13 -0
  16. data/app/components/spotlight/admin_users/site_admin_component.rb +17 -0
  17. data/app/components/spotlight/analytics/aggregation_component.rb +1 -1
  18. data/app/components/spotlight/analytics/dashboard_component.rb +1 -1
  19. data/app/components/spotlight/breadcrumbs_component.rb +1 -1
  20. data/app/components/spotlight/bulk_action_component.rb +1 -1
  21. data/app/components/spotlight/edit_view_links_component.rb +1 -1
  22. data/app/components/spotlight/header_navigation_link_component.rb +1 -1
  23. data/app/components/spotlight/save_search_component.rb +1 -1
  24. data/app/components/spotlight/select_image_component.rb +1 -1
  25. data/app/components/spotlight/skip_link_component.rb +1 -1
  26. data/app/components/spotlight/solr_document_legacy_embed_component.rb +2 -2
  27. data/app/components/spotlight/tag_list_form_component.rb +1 -1
  28. data/app/components/spotlight/tag_selector_component.rb +1 -1
  29. data/app/components/spotlight/title_component.rb +1 -1
  30. data/app/components/spotlight/translations/subheading_component.rb +1 -1
  31. data/app/components/spotlight/uneditable_non_default_language_component.rb +1 -1
  32. data/app/controllers/spotlight/admin_users_controller.rb +11 -1
  33. data/app/controllers/spotlight/browse_controller.rb +2 -8
  34. data/app/controllers/spotlight/bulk_actions_controller.rb +1 -1
  35. data/app/controllers/spotlight/bulk_updates_controller.rb +22 -7
  36. data/app/controllers/spotlight/catalog_controller.rb +7 -15
  37. data/app/controllers/spotlight/dashboards_controller.rb +2 -6
  38. data/app/controllers/spotlight/exhibits_controller.rb +1 -0
  39. data/app/controllers/spotlight/home_pages_controller.rb +1 -1
  40. data/app/controllers/spotlight/searches_controller.rb +1 -1
  41. data/app/controllers/spotlight/solr_controller.rb +1 -0
  42. data/app/helpers/spotlight/main_app_helpers.rb +1 -5
  43. data/app/helpers/spotlight/rendering_helper.rb +4 -1
  44. data/app/javascript/spotlight/admin/blocks/pages_block.js +2 -0
  45. data/app/javascript/spotlight/user/carousel.js +32 -2
  46. data/app/jobs/spotlight/add_tags_job.rb +1 -0
  47. data/app/jobs/spotlight/add_uploads_from_csv.rb +1 -0
  48. data/app/jobs/spotlight/change_visibility_job.rb +1 -0
  49. data/app/jobs/spotlight/process_bulk_updates_csv_job.rb +1 -0
  50. data/app/jobs/spotlight/reindex_exhibit_job.rb +1 -0
  51. data/app/jobs/spotlight/reindex_job.rb +1 -0
  52. data/app/jobs/spotlight/remove_tags_job.rb +1 -0
  53. data/app/jobs/spotlight/rename_sidecar_field_job.rb +1 -0
  54. data/app/models/concerns/spotlight/user.rb +5 -0
  55. data/app/models/sir_trevor_rails/blocks/browse_block.rb +1 -1
  56. data/app/models/sir_trevor_rails/blocks/featured_pages_block.rb +1 -1
  57. data/app/models/sir_trevor_rails/blocks/solr_documents_block.rb +1 -0
  58. data/app/models/spotlight/ability.rb +1 -1
  59. data/app/models/spotlight/about_page.rb +1 -0
  60. data/app/models/spotlight/blacklight_configuration.rb +6 -7
  61. data/app/models/spotlight/contact.rb +2 -1
  62. data/app/models/spotlight/contact_email.rb +1 -0
  63. data/app/models/spotlight/custom_field.rb +1 -0
  64. data/app/models/spotlight/exhibit.rb +2 -9
  65. data/app/models/spotlight/feature_page.rb +1 -0
  66. data/app/models/spotlight/group.rb +2 -1
  67. data/app/models/spotlight/home_page.rb +1 -0
  68. data/app/models/spotlight/job_tracker.rb +1 -1
  69. data/app/models/spotlight/main_navigation.rb +1 -1
  70. data/app/models/spotlight/page.rb +28 -19
  71. data/app/models/spotlight/resource.rb +1 -0
  72. data/app/models/spotlight/resources/iiif_manifest.rb +0 -126
  73. data/app/models/spotlight/resources/iiif_manifest_metadata.rb +161 -0
  74. data/app/models/spotlight/resources/iiif_manifest_v3.rb +41 -0
  75. data/app/models/spotlight/resources/iiif_service.rb +25 -1
  76. data/app/models/spotlight/search.rb +2 -1
  77. data/app/services/spotlight/exhibit_import_export_service.rb +3 -1
  78. data/app/views/spotlight/admin_users/index.html.erb +16 -26
  79. data/app/views/spotlight/catalog/_document_admin_table.html.erb +2 -6
  80. data/app/views/spotlight/catalog/edit.html.erb +1 -6
  81. data/app/views/spotlight/exhibits/_exhibit_card.html.erb +1 -1
  82. data/app/views/spotlight/pages/_order_pages.html.erb +1 -1
  83. data/app/views/spotlight/pages/show.html.erb +4 -2
  84. data/app/views/spotlight/resources/csv_upload/_form.html.erb +2 -0
  85. data/app/views/spotlight/sir_trevor/blocks/_embedded_document.html.erb +2 -2
  86. data/app/views/spotlight/sir_trevor/blocks/_search_results_block.html.erb +2 -2
  87. data/app/views/spotlight/sir_trevor/blocks/_solr_documents_carousel_block.html.erb +5 -3
  88. data/app/views/spotlight/sir_trevor/blocks/_text_block.html.erb +1 -1
  89. data/config/initializers/devise_rails8_patch.rb +13 -0
  90. data/config/locales/spotlight.en.yml +34 -5
  91. data/config/routes.rb +5 -1
  92. data/lib/spotlight/engine.rb +10 -26
  93. data/lib/spotlight/version.rb +1 -1
  94. data/spec/fixtures/iiif_responses.rb +344 -0
  95. data/spec/support/features/test_features_helpers.rb +4 -6
  96. data/spec/support/stub_iiif_response.rb +1 -0
  97. data/spec/support/with_queue_adapter.rb +17 -0
  98. metadata +42 -29
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Spotlight
4
+ module Resources
5
+ # A PORO to construct a solr hash for a given v3 IiifManifest
6
+ class IiifManifestV3 < Spotlight::Resources::IiifManifest
7
+ private
8
+
9
+ def add_thumbnail_url
10
+ return unless thumbnail_field && manifest['thumbnail'].present?
11
+
12
+ solr_hash[thumbnail_field] = manifest.thumbnail.map(&:id)
13
+ end
14
+
15
+ def image_urls
16
+ resources.map do |resource|
17
+ image_url = (resource['id'] || resource['@id']).dup # break reference, otherwise it changes values of other fields
18
+ image_url << '/info.json' unless image_url.downcase.ends_with?('/info.json')
19
+ image_url
20
+ end
21
+ end
22
+
23
+ def full_image_url
24
+ resources.first.try(:[], 'id') || resources.first.try(:[], '@id')
25
+ end
26
+
27
+ def resources
28
+ @resources ||=
29
+ canvases
30
+ .flat_map(&:items).select { |item| item.type == 'AnnotationPage' }
31
+ .flat_map(&:items).select { |item| item.motivation == 'painting' }
32
+ .flat_map(&:body)
33
+ .flat_map(&:service)
34
+ end
35
+
36
+ def canvases
37
+ manifest.try(:items).select { |canvas| canvas.type == 'Canvas' }
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'iiif/presentation'
4
+ require 'iiif/v3/presentation'
4
5
  module Spotlight
5
6
  module Resources
6
7
  ###
@@ -20,6 +21,8 @@ module Spotlight
20
21
  def manifests
21
22
  @manifests ||= if manifest?
22
23
  [create_iiif_manifest(object)]
24
+ elsif v3_manifest?
25
+ [create_iiif_v3_manifest(object)]
23
26
  else
24
27
  build_collection_manifest.to_a
25
28
  end
@@ -39,13 +42,26 @@ module Spotlight
39
42
  protected
40
43
 
41
44
  def object
42
- @object ||= IIIF::Service.parse(response)
45
+ # If it's a v3 manifest, the v2 library will parse it as an OrderedHash
46
+ @object ||= parse_v2? ? manifest_v2 : manifest_v3
43
47
  end
44
48
 
45
49
  private
46
50
 
47
51
  attr_reader :url
48
52
 
53
+ def parse_v2?
54
+ manifest_v2.is_a?(IIIF::Presentation::Manifest) || manifest_v2.is_a?(IIIF::Presentation::Collection)
55
+ end
56
+
57
+ def manifest_v2
58
+ @manifest_v2 ||= IIIF::Presentation::Service.parse(response)
59
+ end
60
+
61
+ def manifest_v3
62
+ IIIF::V3::Presentation::Service.parse(response)
63
+ end
64
+
49
65
  class << self
50
66
  def iiif_response(url)
51
67
  Spotlight::Resources::IiifService.http_client.get(url).body
@@ -73,10 +89,18 @@ module Spotlight
73
89
  IiifManifest.new(url: manifest['@id'], manifest:, collection:)
74
90
  end
75
91
 
92
+ def create_iiif_v3_manifest(manifest, collection = nil)
93
+ IiifManifestV3.new(url: manifest['id'], manifest:, collection:)
94
+ end
95
+
76
96
  def manifest?
77
97
  object.is_a?(IIIF::Presentation::Manifest)
78
98
  end
79
99
 
100
+ def v3_manifest?
101
+ object.is_a?(IIIF::V3::Presentation::Manifest)
102
+ end
103
+
80
104
  def collection?
81
105
  object.is_a?(IIIF::Presentation::Collection)
82
106
  end
@@ -8,6 +8,7 @@ module Spotlight
8
8
  include Spotlight::SearchHelper
9
9
 
10
10
  extend FriendlyId
11
+
11
12
  friendly_id :title, use: %i[slugged scoped finders history], scope: :exhibit
12
13
 
13
14
  self.table_name = 'spotlight_searches'
@@ -25,7 +26,7 @@ module Spotlight
25
26
  serialize :query_params, Hash
26
27
  end
27
28
  end
28
- default_scope { order('weight ASC') }
29
+ default_scope { order(:weight) }
29
30
  scope :published, -> { where(published: true) }
30
31
  scope :unpublished, -> { where(published: [nil, false]) }
31
32
  validates :title, presence: true
@@ -164,12 +164,13 @@ module Spotlight
164
164
 
165
165
  hash[:custom_fields].each do |attr|
166
166
  ar = exhibit.custom_fields.find_or_initialize_by(slug: attr[:slug])
167
- attr[:configuration] = attr[:configuration].clone.transform_keys(&:to_s)
167
+ attr[:configuration] = attr[:configuration].clone.deep_transform_keys(&:to_s) if attr[:configuration]
168
168
  ar.update(attr)
169
169
  end
170
170
 
171
171
  hash[:solr_document_sidecars].each do |attr|
172
172
  ar = exhibit.solr_document_sidecars.find_or_initialize_by(document_id: attr[:document_id])
173
+ attr[:data] = attr[:data].clone.deep_transform_keys(&:to_s) if attr[:data]
173
174
  ar.update(attr)
174
175
  end
175
176
 
@@ -177,6 +178,7 @@ module Spotlight
177
178
  upload = attr.delete(:upload)
178
179
 
179
180
  ar = exhibit.resources.find_or_initialize_by(type: attr[:type], url: attr[:url])
181
+ attr[:data] = attr[:data].clone.deep_transform_keys(&:to_s) if attr[:data]
180
182
  ar.update(attr)
181
183
 
182
184
  deserialize_featured_image(ar, :upload, upload) if upload
@@ -5,20 +5,18 @@
5
5
  <table class="table table-striped">
6
6
  <thead>
7
7
  <tr>
8
- <th colspan="2"><%= Spotlight::Engine.user_class.human_attribute_name(:email) %></th>
8
+ <th scope="col"><%= Spotlight::Engine.user_class.human_attribute_name(:email) %></th>
9
+ <th scope="col"><%= t('.site_admin') %></th>
9
10
  </tr>
10
11
  </thead>
11
- <tbody class="table">
12
+ <tbody>
12
13
  <% @site.roles.map(&:user).each do |user| %>
13
14
  <tr>
14
- <td class="<%= 'invite-pending' if user.invite_pending? %>">
15
- <%= user.email %>
16
- <span class='badge bg-warning pending-label'><%= t('.pending') %></span>
15
+ <td>
16
+ <%= render Spotlight::AdminUsers::EmailComponent.new(user:) %>
17
17
  </td>
18
18
  <td>
19
- <%= link_to(t('.destroy'), admin_user_path(user),
20
- data: { method: :delete, turbo_method: :delete },
21
- class: 'btn btn-sm btn-danger float-end') unless user == current_user %>
19
+ <%= render Spotlight::AdminUsers::SiteAdminComponent.new(user:) %>
22
20
  </td>
23
21
  </tr>
24
22
  <% end %>
@@ -67,30 +65,22 @@
67
65
  <table class="table table-striped ">
68
66
  <thead>
69
67
  <tr>
70
- <th><%= Spotlight::Engine.user_class.human_attribute_name(:email) %></th>
71
- <th><%= Spotlight::Engine.user_class.human_attribute_name(:role) %></th>
68
+ <th scope="col"><%= Spotlight::Engine.user_class.human_attribute_name(:email) %></th>
69
+ <th scope="col"><%= t('.site_admin') %></th>
70
+ <th scope="col"><%= t('.exhibit_roles') %></th>
72
71
  </tr>
73
72
  </thead>
74
- <tbody class="table">
73
+ <tbody>
75
74
  <% @users.each do |user| %>
76
75
  <tr>
77
- <td class="<%= 'invite-pending' if user.invite_pending? %>">
78
- <%= user.email %>
79
- <span class='badge bg-warning pending-label'><%= t('.pending') %></span>
76
+ <td class="user-emails">
77
+ <%= render Spotlight::AdminUsers::EmailComponent.new(user:) %>
80
78
  </td>
81
- <td class="role">
82
- <%= user.roles.map { |r| r.role.titleize }.uniq.join(", ") %>
79
+ <td>
80
+ <%= render Spotlight::AdminUsers::SiteAdminComponent.new(user:) %>
83
81
  </td>
84
- <td class="text-end">
85
- <% if user.superadmin? %>
86
- <%= link_to(t('.destroy'), admin_user_path(user),
87
- data: { method: :delete, turbo_method: :delete },
88
- class: 'btn btn-sm btn-danger') unless user == current_user %>
89
- <% else %>
90
- <%= link_to(t('.update'), admin_user_path(user),
91
- data: { method: :patch, turbo_method: :patch },
92
- class: 'btn btn-sm btn-primary') %>
93
- <% end %>
82
+ <td class="user-exhibit-roles">
83
+ <%= render Spotlight::AdminUsers::ExhibitRolesComponent.new(user:) %>
94
84
  </td>
95
85
  </tr>
96
86
  <% end %>
@@ -10,10 +10,6 @@
10
10
  </tr>
11
11
  </thead>
12
12
 
13
- <% if Blacklight.version < '8.0' %>
14
- <%= render (view_config.document_component || Spotlight::DocumentAdminTableComponent).with_collection(documents) %>
15
- <% else %>
16
- <% document_presenters = documents.map { |doc| document_presenter(doc) } -%>
17
- <%= render view_config.document_component.with_collection(document_presenters) %>
18
- <% end %>
13
+ <% document_presenters = documents.map { |doc| document_presenter(doc) } -%>
14
+ <%= render view_config.document_component.with_collection(document_presenters) %>
19
15
  </table>
@@ -1,13 +1,8 @@
1
1
  <div class="container">
2
2
  <div class="row">
3
3
  <%- view_config = blacklight_config.view_config(action_name: :edit) %>
4
- <%= render (view_config.document_component || Blacklight::DocumentComponent).new((Blacklight.version > '8.0' ? :document : :presenter) => document_presenter(@document), classes: ['col-md-8'], component: :div, show: true, actions: false, partials: view_config.partials) do |component| %>
4
+ <%= render (view_config.document_component || Blacklight::DocumentComponent).new(document: document_presenter(@document), classes: ['col-md-8'], component: :div, show: true, partials: view_config.partials) do |component| %>
5
5
  <% component.with_title(as: 'h1', classes: '', link_to_document: false) %>
6
- <% component.with_body do %>
7
- <% view_config.partials.each do |view_partial| %>
8
- <%= render_document_partial @document, view_partial, component: component, document_counter: 1 %>
9
- <% end %>
10
- <% end if Blacklight.version < '8.0' && view_config.document_component.blank? %>
11
6
  <% end %>
12
7
  <div class="col-md-4">
13
8
  <%= render 'edit_default', document: @document %>
@@ -28,7 +28,7 @@
28
28
 
29
29
  <% if exhibit.description %>
30
30
  <p class="description">
31
- <%= exhibit.description %>
31
+ <%= strip_tags(exhibit.description) %>
32
32
  </p>
33
33
  <% end %>
34
34
  <% end %>
@@ -5,7 +5,7 @@
5
5
 
6
6
  <%= render partial: 'header', locals: {f: f} %>
7
7
  <h2 class="mt-4"><%= t :'.pages_header' %></h2>
8
- <p class="instructions"><%= t :'.instructions' %></p>
8
+ <div class="instructions"><%= t :'.instructions_html' %></div>
9
9
  <div class="panel-group dd <%= page_collection_name %>_admin" id="nested-pages" data-behavior="nestable" <%= nestable_data_attributes(page_collection_name).html_safe %> >
10
10
  <ol class="dd-list">
11
11
  <%= f.fields_for page_collection_name do |p| %>
@@ -9,9 +9,11 @@
9
9
  <div class="clearfix">
10
10
  <%= render 'edit_page_link' if can? :edit, @page %>
11
11
  <% if @page.should_display_title? %>
12
- <h1 class="page-title">
12
+ <h2 class="page-title h1">
13
13
  <%= @page.title %>
14
- </h1>
14
+ </h2>
15
+ <% else %>
16
+ <h2 class="visually-hidden"><%= t '.default_page_title'%></h2>
15
17
  <% end %>
16
18
  </div>
17
19
  <div>
@@ -1,3 +1,5 @@
1
+ <div class="instructions mb-4"><%= t('.instructions_html') %></div>
2
+
1
3
  <%= bootstrap_form_for([current_exhibit, @resource.becomes(Spotlight::Resources::CsvUpload)], layout: :horizontal, label_col: 'col-md-2', control_col: 'col-sm-6 col-md-6', html: { class: 'item-upload-form', multipart: true } ) do |f| %>
2
4
  <%= f.url_field :url, type: "file", help: t('.help_html', link: link_to(t('.template'), template_exhibit_resources_csv_uploads_path, data: { turbo: false })), label: t('.file_label') %>
3
5
  <div class="form-actions">
@@ -1,8 +1,8 @@
1
1
  <div class="box" data-id="<%= document.id %>">
2
2
  <% view_config = blacklight_config.view_config(:embed) %>
3
- <%= render (view_config.document_component || Spotlight::SolrDocumentLegacyEmbedComponent).new((Blacklight.version > '8.0' ? :document : :presenter) => document_presenter(document, view_config: view_config), counter: nil, block: local_assigns[:block]) do |component| %>
3
+ <%= render (view_config.document_component || Spotlight::SolrDocumentLegacyEmbedComponent).new(document: document_presenter(document, view_config: view_config), counter: nil, block: local_assigns[:block]) do |component| %>
4
4
  <% component.with_partial do %>
5
5
  <%= render_document_partials document, view_config.partials, component: component, document_counter: nil, view_config: view_config, block: local_assigns[:block], **(view_config.locals) %>
6
- <% end if view_config&.partials&.any? %>
6
+ <% end if Blacklight.version < '9.0' && view_config&.partials&.any? %>
7
7
  <% end %>
8
8
  </div>
@@ -1,12 +1,12 @@
1
1
  <% if search_results_block.searches? %>
2
2
  <div class="content-block documents">
3
- <% response, document_list = get_search_widget_search_results(search_results_block) %>
3
+ <% response = get_search_widget_search_results(search_results_block) %>
4
4
  <%- unless response.documents.present? %>
5
5
  <div class="alert alert-warning">
6
6
  <strong>No items to display.</strong> There are currently no items in this exhibit that match the curator's search criteria.
7
7
  </div>
8
8
  <%- else %>
9
- <% @response, @document_list = [response, document_list] %>
9
+ <% @response = response %>
10
10
 
11
11
  <% views = blacklight_view_config_for_search_block(search_results_block) %>
12
12
  <% if views.length > 1 -%>
@@ -15,7 +15,7 @@
15
15
  <% elsif doc_presenter.thumbnail.exists? %>
16
16
  <%= doc_presenter.thumbnail.thumbnail_tag({ alt: resource_alt_text(block_options, doc_presenter.heading) }, document_counter: -1) %>
17
17
  <% end %>
18
- <div class="carousel-caption">
18
+ <div class="carousel-caption" id="carousel-caption-<%= document.id %>">
19
19
  <% if solr_documents_carousel_block.primary_caption? %>
20
20
  <h3 class="primary">
21
21
  <%= solr_documents_carousel_block.document_caption(doc_presenter, solr_documents_carousel_block.primary_caption_field) %>
@@ -40,10 +40,12 @@
40
40
  </ol>
41
41
 
42
42
  <!-- Controls -->
43
- <a class="left carousel-control-prev" href="#<%= html_id %>" data-bs-slide="prev">
43
+ <a class="left carousel-control-prev" href="#<%= html_id %>" data-bs-slide="prev"
44
+ aria-label="<%= t('spotlight.sir_trevor.blocks.solr_documents_carousel_block.controls.previous_item') %>">
44
45
  <%= blacklight_icon('arrow_back_ios') %>
45
46
  </a>
46
- <a class="right carousel-control-next" href="#<%= html_id %>" data-bs-slide="next">
47
+ <a class="right carousel-control-next" href="#<%= html_id %>" data-bs-slide="next"
48
+ aria-label="<%= t('spotlight.sir_trevor.blocks.solr_documents_carousel_block.controls.next_item') %>">
47
49
  <%= blacklight_icon('arrow_forward_ios') %>
48
50
  </a>
49
51
  </div>
@@ -1,4 +1,4 @@
1
1
  <div class="st__content-block st__content-block--text">
2
- <%# We prefer the GitHub markup here. %>
2
+ <%# We prefer the Redcarpet markup here. %>
3
3
  <%= sir_trevor_markdown text_block.text %>
4
4
  </div>
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'devise' # make sure it's already loaded
4
+
5
+ # Starting from Rails 8.0, routes are lazy-loaded by default in test and development environments.
6
+ # However, Devise's mappings are built during the routes loading phase.
7
+ # To ensure it works correctly, we need to load the routes first before accessing @@mappings.
8
+ module Devise
9
+ def self.mappings
10
+ Rails.application.try(:reload_routes_unless_loaded)
11
+ @@mappings
12
+ end
13
+ end
@@ -213,13 +213,22 @@ en:
213
213
  admins_curators: Administrators and curators of all exhibits
214
214
  all_users: All registered users
215
215
  copy: Copy
216
- create: Add new administrator
217
- destroy: Remove from admin role
218
- instructions: Existing exhibits administrators
216
+ create: Add new site admin
217
+ destroy: Remove site admin role
218
+ destroy_confirm: Are you sure you want to remove the site admin role for %{email}?
219
+ exhibit_roles: Exhibit roles
220
+ instructions: Existing exhibits site administrators
219
221
  page_title: Manage users
220
222
  pending: pending
223
+ remove_roles: Remove all exhibit roles
224
+ remove_roles_confirm: Are you sure you want to remove all exhibit roles for %{email}?
221
225
  save: Add role
222
- update: Make user an administrator
226
+ show_exhibit_roles: Show exhibit title (role)
227
+ site_admin: Site admin
228
+ update: Make user a site admin
229
+ remove_exhibit_roles:
230
+ error: There was a problem removing the user's exhibit roles
231
+ success: Removed all exhibit roles for user
223
232
  appearances:
224
233
  edit:
225
234
  header: Appearance
@@ -762,16 +771,31 @@ en:
762
771
  header: New page
763
772
  order_pages:
764
773
  cancel: Cancel
765
- instructions: Add new pages below. Drag and drop pages to change the order in which they are displayed in the sidebar.
774
+ instructions_html: |
775
+ <p>Add new pages below. Drag and drop pages to change the order in which they are displayed in the sidebar.</p>
776
+ <p><b>Note About Page Titles and URLs</b></p>
777
+ <p>When renaming pages, keep in mind that Spotlight automatically creates a unique URL (called a slug) based on the page title. If another page is already using that slug—even if it has been renamed—the new page's URL will include extra characters to make it unique.</p>
778
+ <p><b>Tip:</b> If you want a new or renamed page to have a clean URL (e.g., /collection-highlights), make sure to delete the original page that first used that title before renaming.</p>
766
779
  new_page: Add new page
767
780
  pages_header: Custom pages
768
781
  save: Save
782
+ show:
783
+ default_page_title: Main Content
769
784
  resources:
770
785
  csv_upload:
771
786
  form:
772
787
  add_item: Add item
773
788
  file_label: CSV file
774
789
  help_html: "%{link}"
790
+ instructions_html: |
791
+ <p><b>Tips for uploading items via CSV</b></p>
792
+ <ul>
793
+ <li>Only .jpg, .jpeg, or .png files can be uploaded as items.</li>
794
+ <li>Each item file must be under 10 MB.</li>
795
+ <li>Images from phones/tablets may display sideways or upside-down. Re-saving the image in Photoshop or another editor can help correct this.</li>
796
+ <li>Rows with a blank URL field will be skipped. Use ~ to skip the field but still index the item.</li>
797
+ <li>CSVs saved from Excel may include hidden characters. Use a plain text editor to clean and re-save the file if errors occur.</li>
798
+ </ul>
775
799
  template: Download template
776
800
  title: Upload multiple items
777
801
  external_resources_form:
@@ -827,6 +851,7 @@ en:
827
851
  fields:
828
852
  abstract_tesim: Abstract
829
853
  corporate_name_ssm: Corporate names
854
+ exhibit_tags: Exhibit tags
830
855
  facet:
831
856
  corporate_name_ssm: Corporate names
832
857
  exhibit_tags: Exhibit tags
@@ -980,6 +1005,10 @@ en:
980
1005
  other: "%{count} items"
981
1006
  solr_documents_block:
982
1007
  zpr_link_html: View <span class="visually-hidden">%{title}</span> larger
1008
+ solr_documents_carousel_block:
1009
+ controls:
1010
+ next_item: Next item
1011
+ previous_item: Previous item
983
1012
  uploaded_items_block:
984
1013
  zpr_link_html: View <span class="visually-hidden">%{title}</span> larger
985
1014
  sites:
data/config/routes.rb CHANGED
@@ -16,7 +16,11 @@ Spotlight::Engine.routes.draw do
16
16
 
17
17
  get '/exhibits/edit', to: 'sites#edit_exhibits', as: 'edit_site_exhibits'
18
18
 
19
- resources :admin_users, only: %i[index create update destroy]
19
+ resources :admin_users, only: %i[index create update destroy] do
20
+ member do
21
+ delete 'remove_exhibit_roles'
22
+ end
23
+ end
20
24
 
21
25
  resources :exhibits, path: '/', except: [:show] do
22
26
  member do
@@ -25,8 +25,7 @@ module Spotlight
25
25
  isolate_namespace Spotlight
26
26
 
27
27
  require 'carrierwave'
28
- require 'redcarpet' # required for markdown support in github/markup https://github.com/github/markup#markups
29
- require 'github/markup'
28
+ require 'redcarpet' # required for markdown support
30
29
  require 'openseadragon'
31
30
 
32
31
  config.assets.precompile += %w[spotlight/fallback/*.png] if defined?(Sprockets)
@@ -158,7 +157,7 @@ module Spotlight
158
157
  ]
159
158
 
160
159
  config.iiif_manifest_field = :iiif_manifest_url_ssi
161
- config.iiif_metadata_class = -> { Spotlight::Resources::IiifManifest::Metadata }
160
+ config.iiif_metadata_class = -> { Spotlight::Resources::IiifManifestMetadata }
162
161
  config.iiif_collection_id_field = :collection_id_ssim
163
162
  config.iiif_title_fields = nil
164
163
  config.default_json_ld_language = 'en'
@@ -265,31 +264,16 @@ module Spotlight
265
264
 
266
265
  config.spambot_honeypot_email_field = :email_address
267
266
 
268
- if Blacklight::VERSION > '8'
269
- Blacklight::Configuration.default_configuration do
270
- # Field containing the last modified date for a Solr document
271
- Blacklight::Configuration.default_values[:index].timestamp_field ||= 'timestamp'
267
+ Blacklight::Configuration.default_configuration do
268
+ # Field containing the last modified date for a Solr document
269
+ Blacklight::Configuration.default_values[:index].timestamp_field ||= 'timestamp'
272
270
 
273
- # Default configuration for the browse view
274
- Blacklight::Configuration.property :browse, default: Blacklight::OpenStructWithHashAccess.new(document_actions: [])
271
+ # Default configuration for the browse view
272
+ Blacklight::Configuration.property :browse, default: Blacklight::OpenStructWithHashAccess.new(document_actions: [])
275
273
 
276
- Blacklight::Configuration.default_values[:search_state_fields] ||= []
277
- Blacklight::Configuration.default_values[:search_state_fields] += %i[id exhibit_id browse_category_id]
278
- Blacklight::Configuration.default_values[:skip_link_component] = Spotlight::SkipLinkComponent
279
- end
280
- else
281
- config.to_prepare do
282
- Blacklight::Configuration.try(:initialize_default_configuration) unless Blacklight::Configuration.try(:initialized_default_configuration?)
283
-
284
- # Field containing the last modified date for a Solr document
285
- Blacklight::Configuration.default_values[:index].timestamp_field ||= 'timestamp'
286
-
287
- # Default configuration for the browse view
288
- Blacklight::Configuration.default_values[:browse] ||= Blacklight::OpenStructWithHashAccess.new(document_actions: [])
289
-
290
- Blacklight::Configuration.default_values[:search_state_fields] ||= []
291
- Blacklight::Configuration.default_values[:search_state_fields] += %i[id exhibit_id browse_category_id]
292
- end
274
+ Blacklight::Configuration.default_values[:search_state_fields] ||= []
275
+ Blacklight::Configuration.default_values[:search_state_fields] += %i[id exhibit_id browse_category_id]
276
+ Blacklight::Configuration.default_values[:skip_link_component] = Spotlight::SkipLinkComponent
293
277
  end
294
278
 
295
279
  # make blacklight configuration play nice with bootstrap_form
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Spotlight
4
- VERSION = '5.1.0'
4
+ VERSION = '5.2.0'
5
5
  end