blacklight-spotlight 4.7.1 → 5.0.0.pre.alpha2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +30 -12
- data/Rakefile +8 -1
- data/app/assets/javascripts/spotlight/application.js +0 -1
- data/app/assets/javascripts/spotlight/spotlight.esm.js +3621 -3847
- data/app/assets/javascripts/spotlight/spotlight.esm.js.map +1 -1
- data/app/assets/javascripts/spotlight/spotlight.js +3620 -3852
- data/app/assets/javascripts/spotlight/spotlight.js.map +1 -1
- data/app/assets/stylesheets/spotlight/_accessibility.scss +0 -9
- data/app/assets/stylesheets/spotlight/_autocomplete.scss +49 -0
- data/app/assets/stylesheets/spotlight/_blacklight_configuration.scss +0 -1
- data/app/assets/stylesheets/spotlight/_blacklight_overrides.scss +1 -6
- data/app/assets/stylesheets/spotlight/_browse.scss +2 -2
- data/app/assets/stylesheets/spotlight/_catalog.scss +40 -41
- data/app/assets/stylesheets/spotlight/_curation.scss +1 -1
- data/app/assets/stylesheets/spotlight/_exhibit_admin.scss +7 -0
- data/app/assets/stylesheets/spotlight/_exhibits_index.scss +8 -5
- data/app/assets/stylesheets/spotlight/_featured_browse_categories_block.scss +3 -3
- data/app/assets/stylesheets/spotlight/_header.scss +13 -0
- data/app/assets/stylesheets/spotlight/_mixins.scss +3 -4
- data/app/assets/stylesheets/spotlight/_nestable.scss +2 -12
- data/app/assets/stylesheets/spotlight/_pages.scss +11 -9
- data/app/assets/stylesheets/spotlight/_report_a_problem.scss +1 -3
- data/app/assets/stylesheets/spotlight/_sir-trevor_overrides.scss +2 -2
- data/app/assets/stylesheets/spotlight/_spotlight.scss +2 -1
- data/app/assets/stylesheets/spotlight/_tag_selector.scss +34 -0
- data/app/assets/stylesheets/spotlight/_variables.scss +0 -8
- data/app/components/spotlight/analytics/dashboard_component.html.erb +3 -3
- data/app/components/spotlight/blocks/heading_block_component.erb +2 -0
- data/app/components/spotlight/blocks/heading_block_component.rb +36 -0
- data/app/components/spotlight/breadcrumbs_component.html.erb +13 -19
- data/app/components/spotlight/bulk_action_component.rb +1 -1
- data/app/components/spotlight/document_component.rb +1 -1
- data/app/components/spotlight/save_search_component.rb +1 -1
- data/app/components/spotlight/select_image_component.html.erb +17 -0
- data/app/components/spotlight/select_image_component.rb +24 -0
- data/app/components/spotlight/skip_link_component.rb +16 -0
- data/app/components/spotlight/tag_selector_component.html.erb +40 -0
- data/app/components/spotlight/tag_selector_component.rb +41 -0
- data/app/components/spotlight/tag_selector_component.yml +6 -0
- data/app/components/spotlight/title_component.html.erb +8 -0
- data/app/components/spotlight/title_component.rb +22 -0
- data/app/controllers/spotlight/accessibility_controller.rb +2 -2
- data/app/controllers/spotlight/catalog_controller.rb +7 -2
- data/app/controllers/spotlight/contact_email_controller.rb +8 -2
- data/app/controllers/spotlight/languages_controller.rb +9 -4
- data/app/helpers/spotlight/application_helper.rb +7 -0
- data/app/helpers/spotlight/crop_helper.rb +4 -0
- data/app/helpers/spotlight/meta_helper.rb +59 -36
- data/app/javascript/spotlight/admin/blacklight_configuration.js +1 -1
- data/app/javascript/spotlight/admin/block_mixins/autocompleteable.js +70 -34
- data/app/javascript/spotlight/admin/blocks/block.js +1 -0
- data/app/javascript/spotlight/admin/blocks/browse_block.js +8 -12
- data/app/javascript/spotlight/admin/blocks/browse_group_categories_block.js +14 -18
- data/app/javascript/spotlight/admin/blocks/pages_block.js +6 -10
- data/app/javascript/spotlight/admin/blocks/resources_block.js +33 -15
- data/app/javascript/spotlight/admin/blocks/solr_documents_base_block.js +11 -6
- data/app/javascript/spotlight/admin/blocks/solr_documents_embed_block.js +1 -0
- data/app/javascript/spotlight/admin/blocks/uploaded_items_block.js +4 -3
- data/app/javascript/spotlight/admin/copy_email_addresses.js +2 -0
- data/app/javascript/spotlight/admin/crop.js +45 -17
- data/app/javascript/spotlight/admin/croppable.js +8 -1
- data/app/javascript/spotlight/admin/croppable_modal.js +68 -0
- data/app/javascript/spotlight/admin/exhibits.js +15 -10
- data/app/javascript/spotlight/admin/form_observer.js +1 -1
- data/app/javascript/spotlight/admin/index.js +0 -10
- data/app/javascript/spotlight/admin/locks.js +15 -5
- data/app/javascript/spotlight/admin/pages.js +1 -1
- data/app/javascript/spotlight/admin/search_typeahead.js +62 -55
- data/app/javascript/spotlight/admin/spotlight_nestable.js +173 -50
- data/app/javascript/spotlight/admin/visibility_toggle.js +1 -11
- data/app/javascript/spotlight/controllers/index.js +8 -0
- data/app/javascript/spotlight/controllers/tag_selector_controller.js +203 -0
- data/app/javascript/spotlight/core.js +4 -6
- data/app/javascript/spotlight/index.js +2 -0
- data/app/javascript/spotlight/user/browse_group_categories.js +2 -0
- data/app/javascript/spotlight/user/carousel.js +3 -1
- data/app/javascript/spotlight/user/index.js +0 -2
- data/app/javascript/spotlight/user/zpr_links.js +2 -0
- data/app/models/sir_trevor_rails/block.rb +4 -5
- data/app/models/sir_trevor_rails/blocks/solr_documents_block.rb +1 -1
- data/app/models/sir_trevor_rails/blocks/solr_documents_embed_block.rb +1 -1
- data/app/models/sir_trevor_rails/blocks/uploaded_items_block.rb +1 -1
- data/app/models/spotlight/page_configurations.rb +1 -1
- data/app/services/spotlight/exhibit_import_export_service.rb +2 -2
- data/app/views/catalog/_add_tags.html.erb +2 -2
- data/app/views/catalog/_change_visibility.html.erb +1 -1
- data/app/views/catalog/_remove_tags.html.erb +2 -2
- data/app/views/layouts/spotlight/base.html.erb +24 -13
- data/app/views/layouts/spotlight/spotlight.html.erb +6 -6
- data/app/views/shared/_masthead.html.erb +4 -31
- data/app/views/shared/_site_sidebar.html.erb +1 -1
- data/app/views/shared/_user_util_links.html.erb +3 -1
- data/app/views/spotlight/accessibility/alt_text.html.erb +2 -2
- data/app/views/spotlight/admin_users/index.html.erb +3 -3
- data/app/views/spotlight/appearances/edit.html.erb +1 -1
- data/app/views/spotlight/browse/_search_box.html.erb +8 -8
- data/app/views/spotlight/browse/show.html.erb +1 -1
- data/app/views/spotlight/bulk_updates/_download.html.erb +1 -1
- data/app/views/spotlight/bulk_updates/_upload.html.erb +1 -1
- data/app/views/spotlight/catalog/_admin_header.html.erb +1 -1
- data/app/views/spotlight/catalog/_edit_default.html.erb +2 -1
- data/app/views/spotlight/catalog/select_image.html.erb +1 -0
- data/app/views/spotlight/contacts/_form.html.erb +1 -1
- data/app/views/spotlight/exhibits/_contact.html.erb +5 -6
- data/app/views/spotlight/exhibits/_delete.html.erb +1 -1
- data/app/views/spotlight/exhibits/_languages.html.erb +3 -2
- data/app/views/spotlight/featured_images/_form.html.erb +6 -2
- data/app/views/spotlight/featured_images/_upload_form.html.erb +1 -1
- data/app/views/spotlight/metadata_configurations/_metadata_field.html.erb +1 -1
- data/app/views/spotlight/metadata_configurations/edit.html.erb +6 -6
- data/app/views/spotlight/pages/show.html.erb +1 -1
- data/app/views/spotlight/resources/csv_upload/_form.html.erb +1 -1
- data/app/views/spotlight/resources/upload/_form.html.erb +1 -1
- data/app/views/spotlight/roles/index.html.erb +1 -1
- data/app/views/spotlight/searches/_form.html.erb +1 -1
- data/app/views/spotlight/shared/_dd3_item.html.erb +1 -1
- data/app/views/spotlight/sir_trevor/blocks/_browse_group_categories_block.html.erb +1 -1
- data/app/views/spotlight/sir_trevor/blocks/_solr_documents_block.html.erb +1 -1
- data/app/views/spotlight/sir_trevor/blocks/_solr_documents_carousel_block.html.erb +1 -1
- data/app/views/spotlight/sir_trevor/blocks/_uploaded_items_block.html.erb +1 -1
- data/app/views/spotlight/tags/index.html.erb +2 -3
- data/app/views/spotlight/translations/_import.html.erb +2 -2
- data/config/importmap.rb +5 -0
- data/config/locales/spotlight.en.yml +2 -0
- data/config/routes.rb +5 -3
- data/lib/generators/spotlight/assets/generator_common_utilities.rb +36 -0
- data/lib/generators/spotlight/assets/importmap_generator.rb +87 -0
- data/lib/generators/spotlight/assets/propshaft_generator.rb +96 -0
- data/lib/generators/spotlight/assets_generator.rb +22 -0
- data/lib/generators/spotlight/install_generator.rb +8 -36
- data/lib/generators/spotlight/scaffold_resource_generator.rb +1 -1
- data/lib/generators/spotlight/templates/assets/spotlight.scss +6 -0
- data/lib/generators/spotlight/templates/javascript/jquery-shim.js +1 -0
- data/lib/spotlight/engine.rb +7 -6
- data/lib/spotlight/version.rb +1 -1
- data/spec/support/features/capybara_wait_metadata_helper.rb +13 -0
- data/spec/support/features/test_features_helpers.rb +16 -30
- data/vendor/assets/javascripts/tiny-slider.js +3 -0
- metadata +37 -87
- data/app/assets/stylesheets/spotlight/#_accessibility.scss# +0 -12
- data/app/javascript/spotlight/admin/checkbox_submit.js +0 -75
- data/app/javascript/spotlight/admin/exhibit_tag_autocomplete.js +0 -39
- data/app/javascript/spotlight/user/report_a_problem.js +0 -30
- data/app/views/spotlight/browse/_tophat.html.erb +0 -1
- data/app/views/spotlight/catalog/_tophat_default.html.erb +0 -1
- data/app/views/spotlight/home_pages/_tophat.html.erb +0 -2
- data/app/views/spotlight/pages/_tophat.html.erb +0 -1
- data/lib/generators/spotlight/templates/spotlight.js +0 -1
- data/lib/generators/spotlight/templates/spotlight.scss +0 -5
- data/spec/support/features/capybara_default_max_wait_metadata_helper.rb +0 -20
- data/vendor/assets/javascripts/bootstrap-tagsinput.js +0 -530
- data/vendor/assets/javascripts/jquery.serializejson.js +0 -234
- data/vendor/assets/javascripts/nestable.js +0 -645
- data/vendor/assets/javascripts/sir-trevor.js +0 -23508
- data/vendor/assets/javascripts/typeahead.bundle.min.js +0 -7
- data/vendor/assets/stylesheets/bootstrap-tagsinput.css +0 -46
@@ -3,7 +3,7 @@
|
|
3
3
|
module Spotlight
|
4
4
|
# Displays the "Save this search" button and modal
|
5
5
|
class SaveSearchComponent < ViewComponent::Base
|
6
|
-
def initialize(button_classes: 'btn btn-
|
6
|
+
def initialize(button_classes: 'btn btn-outline-primary')
|
7
7
|
@button_classes = button_classes
|
8
8
|
super
|
9
9
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<%= render Blacklight::System::ModalComponent.new do |component| %>
|
2
|
+
<% component.with_title { t('spotlight.pages.form.select_image') } %>
|
3
|
+
<% component.with_body do %>
|
4
|
+
<div class='p-3 m-2'>
|
5
|
+
<input type="hidden" name="select_image_region">
|
6
|
+
<p class="instructions"><%= help_text.html_safe %></p>
|
7
|
+
<div class="mx-3" id="resource_block_iiif_cropper" data-behavior="iiif-cropper" data-cropper-key="select_image_<%=@block_item_id%>" data-index-id="<%=@index_id%>" data-crop-width="120" data-crop-height="120">
|
8
|
+
</div>
|
9
|
+
<% end %>
|
10
|
+
<% component.with_footer do %>
|
11
|
+
<div>
|
12
|
+
<input type='button' class='btn btn-outline-primary' value='Cancel' data-bl-dismiss='modal'>
|
13
|
+
<input id='save-cropping-selection' type='button' class='btn btn-primary' value='Save changes' data-bl-dismiss='modal'>
|
14
|
+
</div>
|
15
|
+
<% end %>
|
16
|
+
<% end %>
|
17
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spotlight
|
4
|
+
# Component to select section of image
|
5
|
+
class SelectImageComponent < ViewComponent::Base
|
6
|
+
def initialize(index_id, block_item_id)
|
7
|
+
super
|
8
|
+
@index_id = index_id
|
9
|
+
@block_item_id = block_item_id
|
10
|
+
end
|
11
|
+
|
12
|
+
def render?
|
13
|
+
true
|
14
|
+
end
|
15
|
+
|
16
|
+
def initial_crop_selection
|
17
|
+
Spotlight::Engine.config.thumbnail_initial_crop_selection
|
18
|
+
end
|
19
|
+
|
20
|
+
def help_text
|
21
|
+
t(:'spotlight.pages.form.instructions_html')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spotlight
|
4
|
+
# Blacklight Skip Link Component with conditional search link for Spotlight
|
5
|
+
class SkipLinkComponent < Blacklight::SkipLinkComponent
|
6
|
+
def initialize(render_search_link: true)
|
7
|
+
@render_search_link = render_search_link
|
8
|
+
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def link_to_search
|
13
|
+
super if @render_search_link
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<div data-controller="tag-selector" class="tag-selector" data-tag-selector-translations-value="<%= translation_data.to_json %>" data-tag-selector-tags-value="<%= selected_tags %>">
|
2
|
+
<% if form.nil? %>
|
3
|
+
<%= text_field_tag field_name, selected_tags_value, class: 'tag-selector-input', placeholder: t('.no_js_placeholder'), data: { tag_selector_target: "tagsField" } %>
|
4
|
+
<% else %>
|
5
|
+
<%= form.text_field field_name, value: selected_tags_value, class: 'tag-selector-input', placeholder: t('.no_js_placeholder'), data: { tag_selector_target: "tagsField" } %>
|
6
|
+
<% end %>
|
7
|
+
<input type="hidden" value="<%= selected_tags_value %>" data-tag-selector-target="initialTags">
|
8
|
+
|
9
|
+
<div class='mb-3'>
|
10
|
+
<div class="tag-selection-wrapper" data-tag-selector-target="tagControlWrapper">
|
11
|
+
<div class="dropdown w-100 mb-3 d-inline-block" data-action="click@window->tag-selector#clickOutside">
|
12
|
+
<div data-tag-selector-target="tagSearchDropdown">
|
13
|
+
<div data-tag-selector-target="selectedTags"></div>
|
14
|
+
<div data-tag-selector-target="tagSearchInputWrapper" class="border rounded-bottom tag-selection-search-bar d-flex">
|
15
|
+
<button type="button" aria-label="toggle dropdown" class="btn btn-link text-secondary me-1 px-2" data-action="click->tag-selector#tagDropdown">
|
16
|
+
<span><%= search_icon_svg %></span>
|
17
|
+
</button>
|
18
|
+
<input class="flex-grow-1" data-action="input->tag-selector#search input->tag-selector#updateSearchResultsPlaceholder input->tag-selector#updateTagToAdd focus->tag-selector#tagDropdown keydown->tag-selector#handleKeydown"
|
19
|
+
data-tag-selector-target="tagSearch" placeholder="<%= t('.search') %>" aria-label="<%= t('.search') %>">
|
20
|
+
<button type="button" aria-label="toggle dropdown" class="dropdown-toggle btn btn-link text-secondary" data-bs-toggle="dropdown" data-action="click->tag-selector#tagDropdown"></button>
|
21
|
+
</div>
|
22
|
+
</div>
|
23
|
+
<div data-tag-selector-target="dropdownContent" class="dropdown-content d-none tags-group border rounded">
|
24
|
+
<% all_tags.each do |tag| %>
|
25
|
+
<label class="d-block">
|
26
|
+
<input type="checkbox" <%= 'checked' if selected?(tag) %> data-action="click->tag-selector#tagUpdate" data-tag-selector-target="searchResultTags" data-tag="<%= tag %>">
|
27
|
+
<%= tag %>
|
28
|
+
</label>
|
29
|
+
<% end %>
|
30
|
+
<% if all_tags.empty? %>
|
31
|
+
<label class="no-results"><%= t('.no_results') %></label>
|
32
|
+
<% end %>
|
33
|
+
<label class="d-none" data-tag-selector-target="addNewTagWrapper">
|
34
|
+
<input type="checkbox" disabled data-action="click->tag-selector#tagCreate" data-tag-selector-target="newTag" data-tag=""> Add new tag
|
35
|
+
</label>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
</div>
|
39
|
+
</div>
|
40
|
+
</div>
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spotlight
|
4
|
+
# Displays a tag selection input
|
5
|
+
# This uses a plain text input that acts-as-taggable-on expects.
|
6
|
+
class TagSelectorComponent < ViewComponent::Base
|
7
|
+
# selected_tags_value is a comma delimited string of tags
|
8
|
+
def initialize(field_name:, all_tags:, selected_tags_value: nil, form: nil)
|
9
|
+
@form = form
|
10
|
+
@field_name = field_name
|
11
|
+
@selected_tags_value = selected_tags_value || ''
|
12
|
+
@all_tags = all_tags&.sort_by { |tag| (tag.respond_to?(:name) ? tag.name : tag).downcase }
|
13
|
+
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def selected_tags
|
18
|
+
selected_tags_value.split(',').map(&:strip)
|
19
|
+
end
|
20
|
+
|
21
|
+
def search_icon_svg
|
22
|
+
render Blacklight::Icons::SearchComponent.new
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# To pass to the JS
|
28
|
+
def translation_data
|
29
|
+
{
|
30
|
+
add_new_tag: t('.add_new_tag'),
|
31
|
+
remove: t('.remove')
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def selected?(tag)
|
36
|
+
selected_tags.include?(tag.respond_to?(:name) ? tag.name : tag)
|
37
|
+
end
|
38
|
+
|
39
|
+
attr_reader :form, :field_name, :selected_tags_value, :all_tags
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<div class="container site-title-container">
|
2
|
+
<div class="site-title-wrapper">
|
3
|
+
<a href="<%= helpers.current_exhibit ? helpers.spotlight.exhibit_path(helpers.current_exhibit) : helpers.spotlight.exhibits_path %>" class="link-unstyled">
|
4
|
+
<%= title %>
|
5
|
+
<%= subtitle %>
|
6
|
+
</a>
|
7
|
+
</div>
|
8
|
+
</div>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spotlight
|
4
|
+
# Draws the title in the masthead
|
5
|
+
class TitleComponent < ViewComponent::Base
|
6
|
+
def initialize(title:, subtitle:)
|
7
|
+
@title = title
|
8
|
+
@subtitle = subtitle
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def title
|
13
|
+
tag.h1 @title, class: 'site-title h2'
|
14
|
+
end
|
15
|
+
|
16
|
+
def subtitle
|
17
|
+
return unless @subtitle
|
18
|
+
|
19
|
+
tag.small(@subtitle, class: 'd-none d-md-block py-2 fs-4')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -9,7 +9,7 @@ module Spotlight
|
|
9
9
|
|
10
10
|
def alt_text
|
11
11
|
# Sort by newest except for the homepage, which is always first
|
12
|
-
pages_with_alt = @exhibit.pages.order(Arel.sql('id = 1 DESC, created_at DESC')).select { |elem| elem.content.any?(&:
|
12
|
+
pages_with_alt = @exhibit.pages.order(Arel.sql('id = 1 DESC, created_at DESC')).select { |elem| elem.content.any?(&:supports_alt_text?) }
|
13
13
|
@pages = pages_with_alt.map { |page| get_alt_info(page) }
|
14
14
|
@has_alt_text = @pages.sum { |page| page[:has_alt_text] }
|
15
15
|
@total_alt_items = @pages.sum { |page| page[:can_have_alt_text] }
|
@@ -23,7 +23,7 @@ module Spotlight
|
|
23
23
|
can_have_alt_text = 0
|
24
24
|
has_alt_text = 0
|
25
25
|
page.content.each do |content|
|
26
|
-
next unless content.
|
26
|
+
next unless content.supports_alt_text?
|
27
27
|
|
28
28
|
content.item&.each_value do |item|
|
29
29
|
can_have_alt_text += 1
|
@@ -30,7 +30,6 @@ module Spotlight
|
|
30
30
|
if Blacklight::VERSION > '8'
|
31
31
|
blacklight_config.show.document_component = Spotlight::DocumentComponent
|
32
32
|
else
|
33
|
-
blacklight_config.show.partials.unshift 'tophat'
|
34
33
|
blacklight_config.show.partials.unshift 'curation_mode_toggle'
|
35
34
|
end
|
36
35
|
end
|
@@ -135,6 +134,12 @@ module Spotlight
|
|
135
134
|
end
|
136
135
|
end
|
137
136
|
|
137
|
+
def select_image
|
138
|
+
@index_id = params[:index_id]
|
139
|
+
@block_item_id = params[:block_item_id]
|
140
|
+
respond_to :html
|
141
|
+
end
|
142
|
+
|
138
143
|
protected
|
139
144
|
|
140
145
|
def load_document
|
@@ -194,7 +199,7 @@ module Spotlight
|
|
194
199
|
def solr_document_params
|
195
200
|
params.require(:solr_document).permit(:exhibit_tag_list,
|
196
201
|
uploaded_resource: [:url],
|
197
|
-
sidecar: [:public, { data:
|
202
|
+
sidecar: [:public, { data: editable_solr_document_params }])
|
198
203
|
end
|
199
204
|
|
200
205
|
def editable_solr_document_params
|
@@ -12,13 +12,19 @@ module Spotlight
|
|
12
12
|
|
13
13
|
def destroy
|
14
14
|
@contact_email.destroy
|
15
|
-
|
15
|
+
respond_to do |format|
|
16
|
+
format.turbo_stream { render turbo_stream: turbo_stream.remove(@contact_email) }
|
17
|
+
format.json { render json: { success: true, error: nil } }
|
18
|
+
end
|
16
19
|
end
|
17
20
|
|
18
21
|
private
|
19
22
|
|
20
23
|
def record_not_found(_error)
|
21
|
-
|
24
|
+
respond_to do |format|
|
25
|
+
format.turbo_stream { head :not_found }
|
26
|
+
format.json { render json: { success: false, error: 'Not Found' }, status: :not_found }
|
27
|
+
end
|
22
28
|
end
|
23
29
|
end
|
24
30
|
end
|
@@ -33,10 +33,15 @@ module Spotlight
|
|
33
33
|
def destroy
|
34
34
|
@language.destroy
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
respond_to do |format|
|
37
|
+
format.turbo_stream { render turbo_stream: turbo_stream.remove(@language) }
|
38
|
+
format.html do
|
39
|
+
redirect_to(
|
40
|
+
spotlight.edit_exhibit_path(@exhibit, tab: 'language'),
|
41
|
+
notice: t(:'helpers.submit.language.destroyed', model: @language.model_name.human.downcase)
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
40
45
|
end
|
41
46
|
|
42
47
|
private
|
@@ -30,6 +30,13 @@ module Spotlight
|
|
30
30
|
current_site.title.presence
|
31
31
|
end
|
32
32
|
|
33
|
+
def content?(field)
|
34
|
+
return content_for?(field) unless Rails.configuration.action_view.annotate_rendered_view_with_filenames && content_for(field).present?
|
35
|
+
|
36
|
+
stripped_content = content_for(field).gsub(/<!-- BEGIN .+? -->/, '').gsub(/<!-- END .+? -->/, '').strip
|
37
|
+
stripped_content.present?
|
38
|
+
end
|
39
|
+
|
33
40
|
# Returns the url for the current page in the new locale. This may be
|
34
41
|
# overridden in downstream applications where our naive use of `url_for`
|
35
42
|
# is insufficient to generate the expected routes
|
@@ -3,17 +3,37 @@
|
|
3
3
|
module Spotlight
|
4
4
|
# HTML <meta> tag helpers
|
5
5
|
module MetaHelper
|
6
|
+
def description(description)
|
7
|
+
content_for(:meta) { ActionController::Base.helpers.tag.meta(name: 'description', content: description) } if description
|
8
|
+
end
|
9
|
+
|
10
|
+
def card(type, &block)
|
11
|
+
card = {}
|
12
|
+
block.call(card) if block_given?
|
13
|
+
content_for(:meta) { build_tags(card, type) }
|
14
|
+
end
|
15
|
+
|
16
|
+
# rubocop:disable Rails/OutputSafety
|
17
|
+
def build_tags(attributes, tag_field)
|
18
|
+
type_fields = { 'og' => 'property', 'twitter' => 'name' }
|
19
|
+
attributes.map do |key, value|
|
20
|
+
ActionController::Base.helpers.tag.meta("#{type_fields[tag_field]}": "#{tag_field}:#{key}", content: value) if value
|
21
|
+
end.compact.join("\n").html_safe
|
22
|
+
end
|
23
|
+
# rubocop:enable Rails/OutputSafety
|
24
|
+
|
6
25
|
def add_exhibit_meta_content
|
7
26
|
exhibit_twitter_card_content
|
8
27
|
exhibit_opengraph_content
|
9
28
|
end
|
10
29
|
|
11
30
|
def exhibit_twitter_card_content
|
12
|
-
|
13
|
-
card
|
14
|
-
card.
|
15
|
-
card
|
16
|
-
card
|
31
|
+
card('twitter') do |card|
|
32
|
+
card['card'] = 'summary'
|
33
|
+
card['url'] = spotlight.exhibit_root_url(current_exhibit)
|
34
|
+
card['title'] = current_exhibit.title
|
35
|
+
card['description'] = current_exhibit.subtitle
|
36
|
+
card['image'] = meta_image if current_exhibit.thumbnail
|
17
37
|
end
|
18
38
|
end
|
19
39
|
|
@@ -22,10 +42,10 @@ module Spotlight
|
|
22
42
|
end
|
23
43
|
|
24
44
|
def exhibit_opengraph_content
|
25
|
-
|
26
|
-
graph
|
27
|
-
graph
|
28
|
-
graph
|
45
|
+
card('og') do |graph|
|
46
|
+
graph['title'] = current_exhibit.title
|
47
|
+
graph['image'] = meta_image if current_exhibit.thumbnail
|
48
|
+
graph['site_name'] = site_title
|
29
49
|
end
|
30
50
|
end
|
31
51
|
|
@@ -35,20 +55,21 @@ module Spotlight
|
|
35
55
|
end
|
36
56
|
|
37
57
|
def page_twitter_card_content(page)
|
38
|
-
|
39
|
-
card
|
40
|
-
card
|
58
|
+
card('twitter') do |card|
|
59
|
+
card['card'] = 'summary_large_image'
|
60
|
+
card['title'] = page.title
|
61
|
+
card['image'] = page.thumbnail.iiif_url if page.thumbnail
|
41
62
|
end
|
42
63
|
end
|
43
64
|
|
44
65
|
def page_opengraph_content(page)
|
45
|
-
|
46
|
-
graph
|
47
|
-
graph
|
48
|
-
graph
|
49
|
-
graph
|
50
|
-
graph
|
51
|
-
graph
|
66
|
+
card('og') do |graph|
|
67
|
+
graph['type'] = 'article'
|
68
|
+
graph['site_name'] = application_name
|
69
|
+
graph['title'] = page.title
|
70
|
+
graph['image'] = page.thumbnail.iiif_url if page.thumbnail
|
71
|
+
graph['article:published_time'] = page.created_at.iso8601
|
72
|
+
graph['article:modified_time'] = page.updated_at.iso8601
|
52
73
|
end
|
53
74
|
end
|
54
75
|
|
@@ -58,20 +79,21 @@ module Spotlight
|
|
58
79
|
end
|
59
80
|
|
60
81
|
def browse_twitter_card_content(browse)
|
61
|
-
|
62
|
-
card
|
63
|
-
card
|
82
|
+
card('twitter') do |card|
|
83
|
+
card['card'] = 'summary_large_image'
|
84
|
+
card['title'] = browse.title
|
85
|
+
card['image'] = browse.thumbnail.iiif_url if browse.thumbnail
|
64
86
|
end
|
65
87
|
end
|
66
88
|
|
67
89
|
def browse_opengraph_content(browse)
|
68
|
-
|
69
|
-
graph
|
70
|
-
graph
|
71
|
-
graph
|
72
|
-
graph
|
73
|
-
graph
|
74
|
-
graph
|
90
|
+
card('og') do |graph|
|
91
|
+
graph['type'] = 'article'
|
92
|
+
graph['site_name'] = application_name
|
93
|
+
graph['title'] = browse.title
|
94
|
+
graph['image'] = browse.thumbnail.iiif_url if browse.thumbnail
|
95
|
+
graph['article:published_time'] = browse.created_at.iso8601
|
96
|
+
graph['article:modified_time'] = browse.updated_at.iso8601
|
75
97
|
end
|
76
98
|
end
|
77
99
|
|
@@ -83,19 +105,20 @@ module Spotlight
|
|
83
105
|
def document_twitter_card_content(document)
|
84
106
|
presenter = document_presenter(document)
|
85
107
|
|
86
|
-
|
87
|
-
card
|
88
|
-
card
|
108
|
+
card('twitter') do |card|
|
109
|
+
card['card'] = 'summary_large_image'
|
110
|
+
card['title'] = presenter.heading
|
111
|
+
card['image'] = document.first(blacklight_config.index.thumbnail_field)
|
89
112
|
end
|
90
113
|
end
|
91
114
|
|
92
115
|
def document_opengraph_content(document)
|
93
116
|
presenter = document_presenter(document)
|
94
117
|
|
95
|
-
|
96
|
-
graph
|
97
|
-
graph
|
98
|
-
graph
|
118
|
+
card('og') do |graph|
|
119
|
+
graph['site_name'] = application_name
|
120
|
+
graph['title'] = presenter.heading
|
121
|
+
graph['image'] = document.first(blacklight_config.index.thumbnail_field)
|
99
122
|
end
|
100
123
|
end
|
101
124
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
import { fetchAutocompleteJSON } from 'spotlight/admin/search_typeahead';
|
2
|
+
|
1
3
|
(function ($){
|
2
4
|
SirTrevor.BlockMixins.Autocompleteable = {
|
3
5
|
mixinName: "Autocompleteable",
|
@@ -7,59 +9,93 @@
|
|
7
9
|
this.on("onRender", this.addAutocompletetoSirTrevorForm);
|
8
10
|
|
9
11
|
if (this['autocomplete_url'] === undefined) {
|
10
|
-
this.autocomplete_url = function() { return $('form[data-autocomplete-url]').data('autocomplete-url')
|
12
|
+
this.autocomplete_url = function() { return $('form[data-autocomplete-url]').data('autocomplete-url'); };
|
13
|
+
}
|
14
|
+
|
15
|
+
if (this['autocomplete_fetch'] === undefined) {
|
16
|
+
this.autocomplete_fetch = this.fetchAutocompleteResults;
|
11
17
|
}
|
12
18
|
|
13
19
|
if (this['transform_autocomplete_results'] === undefined) {
|
14
20
|
this.transform_autocomplete_results = (val) => val
|
15
21
|
}
|
16
22
|
|
23
|
+
if (this['highlight'] === undefined) {
|
24
|
+
this.highlight = function(value) {
|
25
|
+
if (!value) return '';
|
26
|
+
const queryValue = this.getQueryValue().trim();
|
27
|
+
return queryValue ? value.replace(new RegExp(queryValue, 'gi'), '<strong>$&</strong>') : value;
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
17
31
|
if (this['autocomplete_control'] === undefined) {
|
18
|
-
this.autocomplete_control = function() {
|
32
|
+
this.autocomplete_control = function() {
|
33
|
+
const autocompleteID = this.autocompleteID();
|
34
|
+
return `
|
35
|
+
<auto-complete src="${this.autocomplete_url()}" for="${autocompleteID}-popup" fetch-on-empty>
|
36
|
+
<input type="text" name="${autocompleteID}" placeholder="${i18n.t("blocks:autocompleteable:placeholder")}" data-default-typeahead>
|
37
|
+
<ul id="${autocompleteID}-popup"></ul>
|
38
|
+
<div id="${autocompleteID}-popup-feedback" class="sr-only visually-hidden"></div>
|
39
|
+
</auto-complete>
|
40
|
+
` };
|
19
41
|
}
|
20
42
|
|
21
|
-
if (this['
|
22
|
-
this.
|
23
|
-
return {
|
24
|
-
|
25
|
-
url: this.autocomplete_url(),
|
26
|
-
filter: this.transform_autocomplete_results
|
27
|
-
}
|
28
|
-
};
|
29
|
-
};
|
43
|
+
if (this['autocomplete_element_template'] === undefined) {
|
44
|
+
this.autocomplete_element_template = function(item) {
|
45
|
+
return `<li role="option" data-autocomplete-value="${item.id}">${this.autocomplete_template(item)}</li>`
|
46
|
+
}
|
30
47
|
}
|
31
48
|
},
|
32
49
|
|
33
|
-
|
34
|
-
|
35
|
-
if($(this).val() === '') {
|
36
|
-
$(this).data().ttTypeahead.input.trigger('queryChanged', '');
|
37
|
-
}
|
38
|
-
});
|
50
|
+
queryTokenizer: function(query) {
|
51
|
+
return query.trim().toLowerCase().split(/\s+/).filter(Boolean);
|
39
52
|
},
|
40
53
|
|
41
|
-
|
42
|
-
|
54
|
+
filterResults: function(data, query) {
|
55
|
+
const queryStrings = this.queryTokenizer(query);
|
56
|
+
return data.filter(item => {
|
57
|
+
const lowerTitle = item.title.toLowerCase();
|
58
|
+
return queryStrings.some(queryString => lowerTitle.includes(queryString));
|
59
|
+
});
|
60
|
+
},
|
43
61
|
|
44
|
-
|
45
|
-
|
46
|
-
|
62
|
+
fetchAutocompleteResults: async function(url) {
|
63
|
+
const result = await fetchAutocompleteJSON(url);
|
64
|
+
const transformed = this.transform_autocomplete_results(result);
|
65
|
+
this.fetchedData = {};
|
66
|
+
transformed.map(item => this.fetchedData[item.id] = item);
|
67
|
+
return transformed.map(item => this.autocomplete_element_template(item)).join('');
|
68
|
+
},
|
47
69
|
|
48
|
-
|
70
|
+
fetchOnceAndFilterLocalResults: async function(url) {
|
71
|
+
if (this.fetchedData === undefined) {
|
72
|
+
await this.fetchAutocompleteResults(url);
|
49
73
|
}
|
74
|
+
const query = url.searchParams.get('q');
|
75
|
+
const data = Object.values(this.fetchedData);
|
76
|
+
const filteredData = query ? this.filterResults(data, query) : data;
|
77
|
+
return filteredData.map(item => this.autocomplete_element_template(item)).join('');
|
78
|
+
},
|
79
|
+
|
80
|
+
autocompleteID: function() {
|
81
|
+
return this.blockID + '-autocomplete';
|
50
82
|
},
|
51
83
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
84
|
+
getQueryValue: function() {
|
85
|
+
const completer = this.inner.querySelector("auto-complete > input");
|
86
|
+
return completer.value;
|
87
|
+
},
|
88
|
+
|
89
|
+
addAutocompletetoSirTrevorForm: function() {
|
90
|
+
const completer = this.inner.querySelector("auto-complete");
|
91
|
+
completer.fetchResult = this.autocomplete_fetch.bind(this);
|
92
|
+
completer.addEventListener('auto-complete-change', (e) => {
|
93
|
+
const data = this.fetchedData[e.relatedTarget.value];
|
94
|
+
if (e.relatedTarget.value && data) {
|
95
|
+
e.value = e.relatedTarget.value = '';
|
96
|
+
this.createItemPanel({ ...data, display: "true" });
|
97
|
+
}
|
98
|
+
});
|
63
99
|
},
|
64
100
|
},
|
65
101
|
|
@@ -8,22 +8,18 @@ SirTrevor.Blocks.Browse = (function(){
|
|
8
8
|
icon_name: "browse",
|
9
9
|
|
10
10
|
autocomplete_url: function() {
|
11
|
-
return
|
11
|
+
return document.getElementById(this.instanceID).closest('form[data-autocomplete-exhibit-searches-path]').dataset.autocompleteExhibitSearchesPath;
|
12
|
+
},
|
13
|
+
|
14
|
+
autocomplete_fetch: function(url) {
|
15
|
+
return this.fetchOnceAndFilterLocalResults(url);
|
12
16
|
},
|
13
17
|
|
14
18
|
autocomplete_template: function(obj) {
|
15
19
|
const thumbnail = obj.thumbnail_image_url ? `<div class="document-thumbnail"><img class="img-thumbnail" src="${obj.thumbnail_image_url}" /></div>` : ''
|
20
|
+
const description = obj.description ? `<small> ${obj.description}</small>` : '';
|
16
21
|
return `<div class="autocomplete-item${!obj.published ? ' blacklight-private' : ''}">${thumbnail}
|
17
|
-
<span class="autocomplete-title">${obj.full_title}</span
|
18
|
-
},
|
19
|
-
|
20
|
-
bloodhoundOptions: function() {
|
21
|
-
return {
|
22
|
-
prefetch: {
|
23
|
-
url: this.autocomplete_url(),
|
24
|
-
ttl: 0
|
25
|
-
}
|
26
|
-
};
|
22
|
+
<span class="autocomplete-title">${this.highlight(obj.full_title)}</span>${description}</div>`;
|
27
23
|
},
|
28
24
|
|
29
25
|
_itemPanel: function(data) {
|
@@ -36,7 +32,7 @@ SirTrevor.Blocks.Browse = (function(){
|
|
36
32
|
}
|
37
33
|
var resource_id = data.slug || data.id;
|
38
34
|
var markup = `
|
39
|
-
<li class="field
|
35
|
+
<li class="field dd-item dd3-item" data-resource-id="${resource_id}" data-id="${index}" id="${this.formId(index)}">
|
40
36
|
<input type="hidden" name="item[${index}][id]" value="${resource_id}" />
|
41
37
|
<input type="hidden" name="item[${index}][full_title]" value="${(data.full_title || data.title)}" />
|
42
38
|
<input data-property="weight" type="hidden" name="item[${index}][weight]" value="${data.weight}" />
|