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
@@ -13,9 +13,9 @@ module Spotlight
13
13
  role = @exhibit.roles.build
14
14
  authorize! :edit, role
15
15
 
16
- add_breadcrumb t(:'spotlight.exhibits.breadcrumb', title: @exhibit.title), @exhibit
17
- add_breadcrumb t(:'spotlight.configuration.sidebar.header'), exhibit_dashboard_path(@exhibit)
18
- add_breadcrumb t(:'spotlight.configuration.sidebar.users'), exhibit_roles_path(@exhibit)
16
+ add_breadcrumb(t(:'spotlight.exhibits.breadcrumb', title: @exhibit.title), @exhibit)
17
+ add_breadcrumb(t(:'spotlight.configuration.sidebar.header'), exhibit_dashboard_path(@exhibit))
18
+ add_breadcrumb(t(:'spotlight.configuration.sidebar.users'), exhibit_roles_path(@exhibit))
19
19
  end
20
20
 
21
21
  def update_all
@@ -24,7 +24,7 @@ module Spotlight
24
24
  if @exhibit.update(exhibit_params)
25
25
  notice = any_deleted ? t(:'helpers.submit.role.destroyed') : t(:'helpers.submit.role.updated')
26
26
  Spotlight::InviteUsersService.call(resource: @exhibit)
27
- redirect_to exhibit_roles_path(@exhibit), notice: notice
27
+ redirect_to exhibit_roles_path(@exhibit), notice:
28
28
  else
29
29
  flash[:alert] = t(:'helpers.submit.role.batch_error', count: exhibit_params[:roles_attributes].to_unsafe_h.size)
30
30
  render action: 'index'
@@ -19,9 +19,9 @@ module Spotlight
19
19
  end
20
20
 
21
21
  def edit
22
- add_breadcrumb t(:'spotlight.exhibits.breadcrumb', title: @exhibit.title), @exhibit
23
- add_breadcrumb t(:'spotlight.configuration.sidebar.header'), exhibit_dashboard_path(@exhibit)
24
- add_breadcrumb t(:'spotlight.configuration.sidebar.search_configuration'), edit_exhibit_search_configuration_path(@exhibit)
22
+ add_breadcrumb(t(:'spotlight.exhibits.breadcrumb', title: @exhibit.title), @exhibit)
23
+ add_breadcrumb(t(:'spotlight.configuration.sidebar.header'), exhibit_dashboard_path(@exhibit))
24
+ add_breadcrumb(t(:'spotlight.configuration.sidebar.search_configuration'), edit_exhibit_search_configuration_path(@exhibit))
25
25
 
26
26
  @field_metadata = Spotlight::FieldMetadata.new(current_exhibit, blacklight_config.repository, @blacklight_configuration.blacklight_config)
27
27
  end
@@ -30,7 +30,7 @@ module Spotlight
30
30
 
31
31
  def edit
32
32
  @groups = @exhibit.groups
33
- add_breadcrumb @search.full_title, edit_exhibit_search_path(@search.exhibit, @search)
33
+ add_breadcrumb(@search.full_title, edit_exhibit_search_path(@search.exhibit, @search))
34
34
  @exhibit = @search.exhibit
35
35
  end
36
36
 
@@ -78,7 +78,7 @@ module Spotlight
78
78
  else
79
79
  t(:'helpers.submit.search.batch_error', model: Spotlight::Search.model_name.human.pluralize.downcase)
80
80
  end
81
- redirect_back fallback_location: fallback_url, notice: notice
81
+ redirect_back fallback_location: fallback_url, notice:
82
82
  end
83
83
 
84
84
  protected
@@ -94,9 +94,9 @@ module Spotlight
94
94
 
95
95
  def attach_breadcrumbs
96
96
  e = @exhibit || @search&.exhibit
97
- add_breadcrumb t(:'spotlight.exhibits.breadcrumb', title: e.title), e
98
- add_breadcrumb t(:'spotlight.curation.sidebar.header'), exhibit_dashboard_path(e)
99
- add_breadcrumb t(:'spotlight.curation.sidebar.browse'), exhibit_searches_path(e)
97
+ add_breadcrumb(t(:'spotlight.exhibits.breadcrumb', title: e.title), e)
98
+ add_breadcrumb(t(:'spotlight.curation.sidebar.header'), exhibit_dashboard_path(e))
99
+ add_breadcrumb(t(:'spotlight.curation.sidebar.browse'), exhibit_searches_path(e))
100
100
  end
101
101
 
102
102
  def batch_search_params
@@ -9,13 +9,13 @@ module Spotlight
9
9
  load_and_authorize_resource
10
10
 
11
11
  def edit
12
- add_breadcrumb t(:'spotlight.sites.home'), root_url
13
- add_breadcrumb t(:'spotlight.sites.edit.page_title')
12
+ add_breadcrumb(t(:'spotlight.sites.home'), root_url)
13
+ add_breadcrumb(t(:'spotlight.sites.edit.page_title'))
14
14
  end
15
15
 
16
16
  def edit_exhibits
17
- add_breadcrumb t(:'spotlight.sites.home'), root_url
18
- add_breadcrumb t(:'spotlight.sites.edit_exhibits.page_title')
17
+ add_breadcrumb(t(:'spotlight.sites.home'), root_url)
18
+ add_breadcrumb(t(:'spotlight.sites.edit_exhibits.page_title'))
19
19
  end
20
20
 
21
21
  def update
@@ -14,9 +14,9 @@ module Spotlight
14
14
 
15
15
  def index
16
16
  @tags = @exhibit.owned_tags
17
- add_breadcrumb t(:'spotlight.exhibits.breadcrumb', title: @exhibit.title), @exhibit
18
- add_breadcrumb t(:'spotlight.curation.sidebar.header'), exhibit_dashboard_path(@exhibit)
19
- add_breadcrumb t(:'spotlight.curation.sidebar.tags'), exhibit_tags_path(@exhibit)
17
+ add_breadcrumb(t(:'spotlight.exhibits.breadcrumb', title: @exhibit.title), @exhibit)
18
+ add_breadcrumb(t(:'spotlight.curation.sidebar.header'), exhibit_dashboard_path(@exhibit))
19
+ add_breadcrumb(t(:'spotlight.curation.sidebar.tags'), exhibit_tags_path(@exhibit))
20
20
 
21
21
  respond_to do |format|
22
22
  format.html
@@ -21,7 +21,7 @@ module Spotlight
21
21
  if current_exhibit.update(exhibit_params)
22
22
  I18n.reload! # reload since we're memoizing
23
23
  notice = t(:'helpers.submit.spotlight_default.updated', model: current_exhibit.class.model_name.human.downcase)
24
- redirect_to edit_exhibit_translations_path(current_exhibit, language: @language, tab: @tab), notice: notice
24
+ redirect_to edit_exhibit_translations_path(current_exhibit, language: @language, tab: @tab), notice:
25
25
  else
26
26
  render 'edit'
27
27
  end
@@ -31,7 +31,7 @@ module Spotlight
31
31
  if current_exhibit.update(import_exhibit_params)
32
32
  I18n.reload! # reload since we're memoizing
33
33
  notice = t(:'helpers.submit.spotlight_default.updated', model: current_exhibit.class.model_name.human.downcase)
34
- redirect_to edit_exhibit_translations_path(current_exhibit, language: @language), notice: notice
34
+ redirect_to edit_exhibit_translations_path(current_exhibit, language: @language), notice:
35
35
  else
36
36
  render 'edit'
37
37
  end
@@ -40,9 +40,9 @@ module Spotlight
40
40
  private
41
41
 
42
42
  def attach_breadcrumbs
43
- add_breadcrumb t(:'spotlight.exhibits.breadcrumb', title: @exhibit.title), @exhibit
44
- add_breadcrumb t(:'spotlight.curation.sidebar.header'), exhibit_dashboard_path(@exhibit)
45
- add_breadcrumb t(:'spotlight.curation.sidebar.translations')
43
+ add_breadcrumb(t(:'spotlight.exhibits.breadcrumb', title: @exhibit.title), @exhibit)
44
+ add_breadcrumb(t(:'spotlight.curation.sidebar.header'), exhibit_dashboard_path(@exhibit))
45
+ add_breadcrumb(t(:'spotlight.curation.sidebar.translations'))
46
46
  end
47
47
 
48
48
  def exhibit_params
@@ -37,7 +37,7 @@ module Spotlight
37
37
  initial_exception = nil
38
38
 
39
39
  ([self] + additional_locale_routing_scopes).each do |scope|
40
- return scope.public_send(:url_for, params.to_unsafe_h.merge(locale: locale))
40
+ return scope.public_send(:url_for, params.to_unsafe_h.merge(locale:))
41
41
  rescue ActionController::UrlGenerationError => e
42
42
  initial_exception ||= e
43
43
  end
@@ -51,7 +51,7 @@ module Spotlight
51
51
 
52
52
  # Can search for named routes directly in the main app, omitting
53
53
  # the "main_app." prefix
54
- def method_missing(method, *args, &block)
54
+ def method_missing(method, *args, &)
55
55
  if main_app_url_helper?(method)
56
56
  main_app.send(method, *args)
57
57
  else
@@ -11,7 +11,7 @@ module Spotlight
11
11
  concat f.hidden_field(:iiif_image_id)
12
12
  concat f.hidden_field(:iiif_region)
13
13
  concat f.hidden_field(:iiif_tilesource)
14
- concat iiif_cropper_tag(f, initial_crop_selection: initial_crop_selection)
14
+ concat iiif_cropper_tag(f, initial_crop_selection:)
15
15
  end
16
16
  end
17
17
 
@@ -80,5 +80,12 @@ module Spotlight
80
80
  def configurations_for_current_page
81
81
  Spotlight::PageConfigurations.new(context: self, page: @page).as_json
82
82
  end
83
+
84
+ def resource_alt_text(options, default)
85
+ return '' if options[:decorative].present?
86
+ return options[:alt_text] if options[:alt_text].present?
87
+
88
+ default
89
+ end
83
90
  end
84
91
  end
@@ -15,7 +15,7 @@ module Spotlight
15
15
  def page_title(section, title = nil)
16
16
  title ||= t(:'.header', default: '').presence
17
17
 
18
- head_content = t(:'spotlight.html_admin_title', section: section, title: title) if section && title
18
+ head_content = t(:'spotlight.html_admin_title', section:, title:) if section && title
19
19
  head_content ||= section || title
20
20
  set_html_page_title(head_content)
21
21
 
@@ -28,7 +28,7 @@ module Spotlight
28
28
  end
29
29
 
30
30
  def set_html_page_title(title = nil)
31
- @page_title = strip_tags(t(:'spotlight.html_title', title: title || t(:'.title', default: :'.header'), application_name: application_name)).html_safe
31
+ @page_title = strip_tags(t(:'spotlight.html_title', title: title || t(:'.title', default: :'.header'), application_name:)).html_safe
32
32
  end
33
33
  end
34
34
  end
@@ -82,7 +82,7 @@ SirTrevor.Blocks.BrowseGroupCategories = (function(){
82
82
  },
83
83
 
84
84
  item_options: function() { return `
85
- '<label>
85
+ <label>
86
86
  <input type="hidden" name="display-item-counts" value="false" />
87
87
  <input type="checkbox" name="display-item-counts" value="true" checked />
88
88
  ${i18n.t("blocks:browse_group_categories:item_counts")}
@@ -8,10 +8,24 @@ Core.Block.Resources = (function(){
8
8
  formable: true,
9
9
  autocompleteable: true,
10
10
  show_heading: true,
11
+ show_alt_text: true,
11
12
 
12
13
  title: function() { return i18n.t("blocks:" + this.type + ":title"); },
13
14
  description: function() { return i18n.t("blocks:" + this.type + ":description"); },
14
-
15
+ alt_text_guidelines: function() {
16
+ if (this.show_alt_text) {
17
+ return i18n.t("blocks:alt_text_guidelines:intro");
18
+ }
19
+ return "";
20
+ },
21
+ alt_text_guidelines_link: function() {
22
+ if (this.show_alt_text) {
23
+ var link_url = i18n.t("blocks:alt_text_guidelines:link_url");
24
+ var link_label = i18n.t("blocks:alt_text_guidelines:link_label");
25
+ return '<a target="_blank" href="' + link_url + '">' + link_label + '</a>';
26
+ }
27
+ return "";
28
+ },
15
29
  icon_name: "resources",
16
30
  blockGroup: function() { return i18n.t("blocks:group:items") },
17
31
 
@@ -21,6 +35,8 @@ Core.Block.Resources = (function(){
21
35
  show_secondary_field_key: "show-secondary-caption",
22
36
 
23
37
  display_checkbox: "display-checkbox",
38
+ decorative_checkbox: "decorative-checkbox",
39
+ alt_text_textarea: "alt-text-textarea",
24
40
 
25
41
  globalIndex: 0,
26
42
 
@@ -28,6 +44,13 @@ Core.Block.Resources = (function(){
28
44
  return [];
29
45
  },
30
46
 
47
+ _altTextFieldsHTML: function(index, data) {
48
+ if (this.show_alt_text) {
49
+ return this.altTextHTML(index, data);
50
+ }
51
+ return "";
52
+ },
53
+
31
54
  _itemPanel: function(data) {
32
55
  var index = "item_" + this.globalIndex++;
33
56
  var checked;
@@ -58,6 +81,7 @@ Core.Block.Resources = (function(){
58
81
  <div class="main">
59
82
  <div class="title card-title">${data.title}</div>
60
83
  <div>${(data.slug || data.id)}</div>
84
+ ${this._altTextFieldsHTML(index, data)}
61
85
  </div>
62
86
  <div class="remove float-right float-end">
63
87
  <a data-item-grid-panel-remove="true" href="#">${i18n.t("blocks:resources:panel:remove")}</a>
@@ -94,6 +118,7 @@ Core.Block.Resources = (function(){
94
118
 
95
119
  createItemPanel: function(data) {
96
120
  var panel = this._itemPanel(data);
121
+ this.attachAltTextHandlers(panel);
97
122
  $(panel).appendTo($('.panels > ol', this.inner));
98
123
  $('[data-behavior="nestable"]', this.inner).trigger('change');
99
124
  },
@@ -126,11 +151,67 @@ Core.Block.Resources = (function(){
126
151
  return `<div class="form resources-admin clearfix">
127
152
  <div class="widget-header">
128
153
  ${this.description()}
154
+ ${this.alt_text_guidelines()}
155
+ ${this.alt_text_guidelines_link()}
129
156
  </div>
130
157
  ${this.content()}
131
158
  </div>`
132
159
  },
133
160
 
161
+ _altTextData: function(data) {
162
+ const isDecorative = data.decorative;
163
+ const altText = isDecorative ? '' : (data.alt_text || '');
164
+ const altTextBackup = data.alt_text_backup || '';
165
+ const placeholderAttr = isDecorative ? '' : `placeholder="${i18n.t("blocks:resources:alt_text:placeholder")}"`;
166
+ const disabledAttr = isDecorative ? 'disabled' : '';
167
+
168
+ return { isDecorative, altText, altTextBackup, placeholderAttr, disabledAttr };
169
+ },
170
+
171
+ altTextHTML: function(index, data) {
172
+ const { isDecorative, altText, altTextBackup, placeholderAttr, disabledAttr } = this._altTextData(data);
173
+ return `<div class="mt-2 pt-2 d-flex">
174
+ <div class="me-2 mr-2">
175
+ <label class="col-form-label pb-0 pt-1" for="${this.formId(this.alt_text_textarea + '_' + data.id)}">${i18n.t("blocks:resources:alt_text:alternative_text")}</label>
176
+ <div class="form-check mb-1 justify-content-end">
177
+ <input class="form-check-input" type="checkbox"
178
+ id="${this.formId(this.decorative_checkbox + '_' + data.id)}" name="item[${index}][decorative]" ${isDecorative ? 'checked' : ''}>
179
+ <label class="form-check-label" for="${this.formId(this.decorative_checkbox + '_' + data.id)}">${i18n.t("blocks:resources:alt_text:decorative")}</label>
180
+ </div>
181
+ </div>
182
+ <div class="flex-grow-1 flex-fill d-flex">
183
+ <input type="hidden" name="item[${index}][alt_text_backup]" value="${altTextBackup}" />
184
+ <textarea class="form-control w-100" rows="2" ${placeholderAttr}
185
+ id="${this.formId(this.alt_text_textarea + '_' + data.id)}" name="item[${index}][alt_text]" ${disabledAttr}>${altText}</textarea>
186
+ </div>
187
+ </div>`
188
+ },
189
+
190
+ attachAltTextHandlers: function(panel) {
191
+ if (this.show_alt_text) {
192
+ const decorativeCheckbox = $('input[name$="[decorative]"]', panel);
193
+ const altTextInput = $('textarea[name$="[alt_text]"]', panel);
194
+ const altTextBackupInput = $('input[name$="[alt_text_backup]"]', panel);
195
+
196
+ decorativeCheckbox.on('change', function() {
197
+ const isDecorative = this.checked;
198
+ if (isDecorative) {
199
+ altTextBackupInput.val(altTextInput.val());
200
+ altTextInput.val('');
201
+ } else {
202
+ altTextInput.val(altTextBackupInput.val());
203
+ }
204
+ altTextInput
205
+ .prop('disabled', isDecorative)
206
+ .attr('placeholder', isDecorative ? '' : i18n.t("blocks:resources:alt_text:placeholder"));
207
+ });
208
+
209
+ altTextInput.on('input', function() {
210
+ $(this).data('lastValue', $(this).val());
211
+ });
212
+ }
213
+ },
214
+
134
215
  onBlockRender: function() {
135
216
  SpotlightNestable.init($('[data-behavior="nestable"]', this.inner));
136
217
 
@@ -4,7 +4,7 @@ SirTrevor.Blocks.SolrDocumentsEmbed = (function(){
4
4
 
5
5
  return SirTrevor.Blocks.SolrDocumentsBase.extend({
6
6
  type: "solr_documents_embed",
7
-
7
+ show_alt_text: false,
8
8
  icon_name: "item_embed",
9
9
 
10
10
  item_options: function() { return "" },
@@ -96,6 +96,7 @@ SirTrevor.Blocks.UploadedItems = (function(){
96
96
  <label for="${this.formId('link_' + dataId)}" class="col-form-label col-md-3">${i18n.t("blocks:uploaded_items:link")}</label>
97
97
  <input type="text" class="form-control col" id="${this.formId('link_' + dataId)}" name="item[${index}][link]" data-field="link"/>
98
98
  </div>
99
+ ${this._altTextFieldsHTML(index, data)}
99
100
  </div>
100
101
  <div class="remove float-right float-end">
101
102
  <a data-item-grid-panel-remove="true" href="#">${i18n.t("blocks:resources:panel:remove")}</a>
@@ -123,6 +124,8 @@ SirTrevor.Blocks.UploadedItems = (function(){
123
124
  return `<div class="form oembed-text-admin clearfix">
124
125
  <div class="widget-header">
125
126
  ${this.description()}
127
+ ${this.alt_text_guidelines()}
128
+ ${this.alt_text_guidelines_link()}
126
129
  </div>
127
130
  <div class="row">
128
131
  <div class="form-group mb-3 col-md-8">
@@ -142,6 +145,24 @@ SirTrevor.Blocks.UploadedItems = (function(){
142
145
  </div>`
143
146
  },
144
147
 
148
+ altTextHTML: function(index, data) {
149
+ const { isDecorative, altText, altTextBackup, placeholderAttr, disabledAttr } = this._altTextData(data);
150
+ return `
151
+ <div class="field row mr-3 me-3">
152
+ <div class="col-lg-3 ps-md-2 pl-md-2">
153
+ <label class="col-form-label text-nowrap pb-0 pt-1 justify-content-md-start justify-content-lg-end d-flex" for="${this.formId(this.alt_text_textarea + '_' + data.id)}">${i18n.t("blocks:resources:alt_text:alternative_text")}</label>
154
+ <div class="form-check d-flex justify-content-md-start justify-content-lg-end">
155
+ <input class="form-check-input" type="checkbox"
156
+ id="${this.formId(this.decorative_checkbox + '_' + data.id)}" name="item[${index}][decorative]" ${isDecorative ? 'checked' : ''}>
157
+ <label class="form-check-label" for="${this.formId(this.decorative_checkbox + '_' + data.id)}">${i18n.t("blocks:resources:alt_text:decorative")}</label>
158
+ </div>
159
+ </div>
160
+ <input type="hidden" name="item[${index}][alt_text_backup]" value="${altTextBackup}" />
161
+ <textarea class="col-lg-9" rows="2" ${placeholderAttr}
162
+ id="${this.formId(this.alt_text_textarea + '_' + data.id)}" name="item[${index}][alt_text]" ${disabledAttr}>${altText}</textarea>
163
+ </div>`
164
+ },
165
+
145
166
  zpr_key: 'zpr_link'
146
167
  });
147
168
  })();
@@ -43,5 +43,32 @@ export default class {
43
43
  return false;
44
44
  });
45
45
  })
46
+
47
+ $("[data-behavior='restore-default']").each(function(){
48
+ var hidden = $("[data-default-value]", $(this));
49
+ var value = $($("[data-in-place-edit-target]", $(this)).data('in-place-edit-target'), $(this));
50
+ var button = $("[data-restore-default]", $(this));
51
+
52
+ hidden.on('keypress', function(e) {
53
+ if(e.which == 13) {
54
+ hidden.trigger('blur');
55
+ return false;
56
+ }
57
+ });
58
+
59
+ hidden.on('blur', function(){
60
+ if( $(this).val() == $(this).data('default-value') ) {
61
+ button.addClass('d-none');
62
+ } else {
63
+ button.removeClass('d-none');
64
+ }
65
+ });
66
+ button.on('click', function(e){
67
+ e.preventDefault();
68
+ hidden.val(hidden.data('default-value'));
69
+ value.text(hidden.data('default-value'));
70
+ button.hide();
71
+ });
72
+ });
46
73
  }
47
74
  }
@@ -8,7 +8,6 @@ import 'Path.Drag'
8
8
 
9
9
  import AddAnother from 'spotlight/admin/add_another'
10
10
  import AddNewButton from 'spotlight/admin/add_new_button'
11
- import Appearance from 'spotlight/admin/appearance'
12
11
  import BlacklightConfiguration from 'spotlight/admin/blacklight_configuration'
13
12
  import CopyEmailAddress from 'spotlight/admin/copy_email_addresses'
14
13
  import Croppable from 'spotlight/admin/croppable'
@@ -60,7 +59,6 @@ export default class {
60
59
  connect() {
61
60
  new AddAnother().connect()
62
61
  new AddNewButton().connect()
63
- new Appearance().connect()
64
62
  new CopyEmailAddress().connect()
65
63
  new Croppable().connect()
66
64
  new EditInPlace().connect()
@@ -51,6 +51,11 @@ SirTrevor.Locales.en.blocks = $.extend(SirTrevor.Locales.en.blocks, {
51
51
  drag: "Drag",
52
52
  display: "Display?",
53
53
  remove: "Remove"
54
+ },
55
+ alt_text: {
56
+ decorative: "Decorative",
57
+ alternative_text: "Alternative text",
58
+ placeholder: "Enter alt text for this item..."
54
59
  }
55
60
  },
56
61
 
@@ -116,5 +121,11 @@ SirTrevor.Locales.en.blocks = $.extend(SirTrevor.Locales.en.blocks, {
116
121
  group: {
117
122
  undefined: "Standard widgets",
118
123
  items: "Exhibit item widgets"
124
+ },
125
+
126
+ alt_text_guidelines: {
127
+ intro: 'For each item, please enter alternative text or appropriately check the decorative box. ',
128
+ link_label: 'Guidelines for writing alt text.',
129
+ link_url: 'https://www.w3.org/WAI/tutorials/images/'
119
130
  }
120
131
  });
@@ -55,7 +55,7 @@ module Spotlight
55
55
  private
56
56
 
57
57
  def find_or_initialize_job_tracker
58
- JobTracker.find_or_create_by(job_id: job_id) do |tracker|
58
+ JobTracker.find_or_create_by(job_id:) do |tracker|
59
59
  tracker.job_class = self.class.name
60
60
  tracker.status = 'enqueued'
61
61
  end
@@ -19,12 +19,12 @@ module Spotlight
19
19
  document.reindex(update_params: {})
20
20
  progress&.increment
21
21
  rescue StandardError => e
22
- job_tracker.append_log_entry(type: :error, exhibit: exhibit, message: e.to_s)
22
+ job_tracker.append_log_entry(type: :error, exhibit:, message: e.to_s)
23
23
  @errors += 1
24
24
  mark_job_as_failed!
25
25
  end
26
26
  exhibit.blacklight_config.repository.connection.commit
27
- job_tracker.append_log_entry(type: :info, exhibit: exhibit, message: "#{progress.progress} of #{progress.total} (#{@errors} errors)")
27
+ job_tracker.append_log_entry(type: :info, exhibit:, message: "#{progress.progress} of #{progress.total} (#{@errors} errors)")
28
28
  end
29
29
  # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
30
30
  end
@@ -44,7 +44,7 @@ module Spotlight
44
44
 
45
45
  resource = Spotlight::Resources::Upload.new(
46
46
  data: row,
47
- exhibit: exhibit
47
+ exhibit:
48
48
  )
49
49
  resource.build_upload(remote_image_url: url) unless url == '~'
50
50
 
@@ -21,12 +21,12 @@ module Spotlight
21
21
  document.reindex(update_params: {})
22
22
  progress&.increment
23
23
  rescue StandardError => e
24
- job_tracker.append_log_entry(type: :error, exhibit: exhibit, message: e.to_s)
24
+ job_tracker.append_log_entry(type: :error, exhibit:, message: e.to_s)
25
25
  @errors += 1
26
26
  mark_job_as_failed!
27
27
  end
28
28
  exhibit.blacklight_config.repository.connection.commit
29
- job_tracker.append_log_entry(type: :info, exhibit: exhibit, message: "#{progress.progress} of #{progress.total} (#{@errors} errors)")
29
+ job_tracker.append_log_entry(type: :info, exhibit:, message: "#{progress.progress} of #{progress.total} (#{@errors} errors)")
30
30
  end
31
31
  # rubocop:enable Metrics/MethodLength
32
32
  end
@@ -20,13 +20,13 @@ module Spotlight
20
20
  process_row(exhibit, row)
21
21
  progress&.increment
22
22
  rescue StandardError => e
23
- job_tracker.append_log_entry(type: :error, exhibit: exhibit, message: e.to_s)
23
+ job_tracker.append_log_entry(type: :error, exhibit:, message: e.to_s)
24
24
  errors += 1
25
25
  mark_job_as_failed!
26
26
  end
27
27
 
28
28
  exhibit.blacklight_config.repository.connection.commit
29
- job_tracker.append_log_entry(type: :info, exhibit: exhibit, message: "#{progress&.progress} of #{progress&.total} (#{errors} errors)")
29
+ job_tracker.append_log_entry(type: :info, exhibit:, message: "#{progress&.progress} of #{progress&.total} (#{errors} errors)")
30
30
  end
31
31
  end
32
32
  # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
@@ -30,7 +30,7 @@ module Spotlight
30
30
 
31
31
  def perform_later_in_batches(exhibit, of:)
32
32
  last = 0
33
- exhibit.resources.select(:id).in_batches(of: of) do |batch|
33
+ exhibit.resources.select(:id).in_batches(of:) do |batch|
34
34
  last = batch.last.id
35
35
  Spotlight::ReindexJob.perform_later(exhibit, reports_on: job_tracker, start: batch.first.id, finish: batch.last.id)
36
36
  end
@@ -29,7 +29,7 @@ module Spotlight
29
29
  error_handler = lambda do |pipeline, exception, _data|
30
30
  job_tracker.append_log_entry(
31
31
  type: :error,
32
- exhibit: exhibit,
32
+ exhibit:,
33
33
  message: exception.to_s,
34
34
  backtrace: exception.backtrace.first(5).join("\n"),
35
35
  resource_id: (pipeline.source.id if pipeline.source.respond_to?(:id))
@@ -38,8 +38,8 @@ module Spotlight
38
38
  errors += 1
39
39
  end
40
40
 
41
- resource_list(exhibit_or_resources, start: start, finish: finish).each do |resource|
42
- resource.reindex(touch: false, commit: false, job_tracker: job_tracker, additional_data: job_data, on_error: error_handler) do |*|
41
+ resource_list(exhibit_or_resources, start:, finish:).each do |resource|
42
+ resource.reindex(touch: false, commit: false, job_tracker:, additional_data: job_data, on_error: error_handler) do |*|
43
43
  progress&.increment
44
44
  end
45
45
  rescue StandardError => e
@@ -48,14 +48,14 @@ module Spotlight
48
48
 
49
49
  job_tracker.append_log_entry(
50
50
  type: :summary,
51
- exhibit: exhibit,
51
+ exhibit:,
52
52
  message: I18n.t(
53
53
  'spotlight.job_trackers.show.messages.status.in_progress',
54
54
  progress: progress.progress,
55
55
  total: progress.total,
56
56
  errors: (I18n.t('spotlight.job_trackers.show.messages.errors', count: errors) if errors.positive?)
57
57
  ),
58
- progress: progress.progress, total: progress.total, errors: errors
58
+ progress: progress.progress, total: progress.total, errors:
59
59
  )
60
60
  end
61
61
  # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
@@ -85,7 +85,7 @@ module Spotlight
85
85
 
86
86
  def resource_list(exhibit_or_resources, start: nil, finish: nil)
87
87
  if exhibit_or_resources.is_a?(Spotlight::Exhibit)
88
- exhibit_or_resources.resources.find_each(start: start, finish: finish)
88
+ exhibit_or_resources.resources.find_each(start:, finish:)
89
89
  else
90
90
  Array(exhibit_or_resources)
91
91
  end
@@ -19,12 +19,12 @@ module Spotlight
19
19
  document.reindex(update_params: {})
20
20
  progress&.increment
21
21
  rescue StandardError => e
22
- job_tracker.append_log_entry(type: :error, exhibit: exhibit, message: e.to_s)
22
+ job_tracker.append_log_entry(type: :error, exhibit:, message: e.to_s)
23
23
  @errors += 1
24
24
  mark_job_as_failed!
25
25
  end
26
26
  exhibit.blacklight_config.repository.connection.commit
27
- job_tracker.append_log_entry(type: :info, exhibit: exhibit, message: "#{progress.progress} of #{progress.total} (#{@errors} errors)")
27
+ job_tracker.append_log_entry(type: :info, exhibit:, message: "#{progress.progress} of #{progress.total} (#{@errors} errors)")
28
28
  end
29
29
  # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
30
30
  end
@@ -20,13 +20,13 @@ module Spotlight
20
20
  exhibit.tag(sidecar, with: all_tags, on: :tags)
21
21
  sidecar.document.reindex(update_params: {})
22
22
  rescue StandardError => e
23
- job_tracker.append_log_entry(type: :error, exhibit: exhibit, message: e.to_s)
23
+ job_tracker.append_log_entry(type: :error, exhibit:, message: e.to_s)
24
24
  @errors += 1
25
25
  mark_job_as_failed!
26
26
  end
27
27
 
28
28
  exhibit.blacklight_config.repository.connection.commit
29
- job_tracker.append_log_entry(type: :info, exhibit: exhibit, message: "#{progress.progress} of #{progress.total} (#{@errors} errors)")
29
+ job_tracker.append_log_entry(type: :info, exhibit:, message: "#{progress.progress} of #{progress.total} (#{@errors} errors)")
30
30
  end
31
31
  # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
32
32
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Breadcrumb model
4
+ class Breadcrumb
5
+ attr_reader :name, :path
6
+
7
+ def initialize(name, path)
8
+ @name = name
9
+ @path = path
10
+ end
11
+
12
+ def link?
13
+ @path.present?
14
+ end
15
+ end
@@ -35,7 +35,7 @@ module Spotlight
35
35
 
36
36
  def initialize_main_navigation
37
37
  default_main_navigations.each_with_index do |nav_type, weight|
38
- main_navigations.create nav_type: nav_type, weight: weight
38
+ main_navigations.create nav_type:, weight:
39
39
  end
40
40
  end
41
41