diff --git a/.rubocop.yml b/.rubocop.yml index b263a973..19dd9ca6 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -36,7 +36,7 @@ Metrics/MethodLength: Enabled: false Metrics/BlockLength: - Max: 28 + Max: 31 Style/BlockDelimiters: Exclude: diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 80bcee9f..eb6aae6a 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -32,6 +32,7 @@ RSpec/MultipleExpectations: # Configuration parameters: MaxNesting. RSpec/NestedGroups: Exclude: + - 'spec/helpers/index_helper_spec.rb' - 'spec/models/iiif_resource_spec.rb' # Offense count: 2 @@ -43,4 +44,5 @@ RSpec/SubjectStub: # Configuration parameters: IgnoreSymbolicNames. RSpec/VerifiedDoubles: Exclude: + - 'spec/presenters/rtl_index_presenter_spec.rb' - 'spec/presenters/rtl_show_presenter_spec.rb' diff --git a/Rakefile b/Rakefile index d4f74a76..98c193da 100644 --- a/Rakefile +++ b/Rakefile @@ -5,6 +5,7 @@ require File.expand_path('../config/application', __FILE__) require 'rubocop/rake_task' require 'sneakers/tasks' require 'solr_wrapper' +require 'solr_wrapper/rake_task' Rails.application.load_tasks diff --git a/app/controllers/catalog_controller.rb b/app/controllers/catalog_controller.rb index d74fa685..d63faba2 100644 --- a/app/controllers/catalog_controller.rb +++ b/app/controllers/catalog_controller.rb @@ -11,7 +11,6 @@ def search_across_settings blacklight_config.add_facet_field 'readonly_language_ssim', label: 'Language' blacklight_config.add_facet_field 'readonly_format_ssim', label: 'Format' - blacklight_config.show.document_presenter_class = RTLShowPresenter unique_custom_fields.each do |field| blacklight_config.add_show_field field.field, label: field.configuration["label"] end @@ -48,6 +47,7 @@ def unique_custom_fields # solr field configuration for search results/index views config.index.title_field = 'full_title_ssim' + config.index.display_title_field = 'readonly_title_tesim' config.add_show_field 'creator_ssim', label: 'Creator' config.add_search_field 'all_fields', label: 'Everything' @@ -60,5 +60,7 @@ def unique_custom_fields config.add_facet_fields_to_solr_request! config.add_field_configuration_to_solr_request! config.response_model = AdjustedGroupedResponse + config.show.document_presenter_class = RTLShowPresenter + config.index.document_presenter_class = RTLIndexPresenter end end diff --git a/app/helpers/index_helper.rb b/app/helpers/index_helper.rb new file mode 100644 index 00000000..c65a2e1e --- /dev/null +++ b/app/helpers/index_helper.rb @@ -0,0 +1,18 @@ +module IndexHelper + def render_index_document(document) + field = index_presenter(document).label(document_show_link_field(document)) + span = [] + if !field.is_a?(Array) + span << content_tag(:span, style: 'display: block;', dir: field.dir) do + link_to(field, url_for_document(document), document_link_params(document, {})) + end + else + field.each do |value| + span << content_tag(:span, style: 'display: block;', dir: value.dir) do + link_to(value, url_for_document(document), document_link_params(document, {})) + end + end + end + safe_join span + end +end diff --git a/app/presenters/rtl_index_presenter.rb b/app/presenters/rtl_index_presenter.rb new file mode 100644 index 00000000..e1b8a602 --- /dev/null +++ b/app/presenters/rtl_index_presenter.rb @@ -0,0 +1,43 @@ +class RTLIndexPresenter < ::Blacklight::IndexPresenter + # Override the IndexPresenter label method to render + # the label as an Array if it's multivalued. + def label(field_or_string_or_proc, opts = {}) + config = Blacklight::Configuration::NullField.new + value = case field_or_string_or_proc + when Symbol + config = field_config(field_or_string_or_proc) + value_from_symbol(field_or_string_or_proc) + when Proc + field_or_string_or_proc.call(@document, opts) + when String + field_or_string_or_proc + end + value ||= @document.id + label_value(value, config) + end + + private + + # Checks if the requested field is the title field and if the configured + # display title field exists on the document. If so, it returns the + # display title field value. This method allows pom to properly display + # records with non-standard title fields. + def value_from_symbol(field) + default_title_field = @configuration.index.title_field.to_sym + display_title_field = @configuration.index.display_title_field.to_sym + + if field == default_title_field && @document.key?(display_title_field) + @document[display_title_field] + else + @document[field] + end + end + + def label_value(value, config) + if value.is_a?(Array) && value.count > 1 + value.collect { |v| field_values(config, value: v) } + else + field_values(config, value: value) + end + end +end diff --git a/app/views/catalog/_index_header_default.html.erb b/app/views/catalog/_index_header_default.html.erb new file mode 100644 index 00000000..89e9e199 --- /dev/null +++ b/app/views/catalog/_index_header_default.html.erb @@ -0,0 +1,25 @@ +<%# header bar for doc items in index view -%> +
+ <%# main title container for doc partial view + How many bootstrap columns need to be reserved + for bookmarks control depends on size. + -%> + <% document_actions = capture do %> + <% # bookmark functions for items/docs -%> + <%= render_index_doc_actions document, wrapping_class: "index-document-functions col-sm-3 col-lg-2" %> + <% end %> + +

"> + + <% if counter = document_counter_with_offset(document_counter) %> + + <%= t('blacklight.search.documents.counter', counter: counter) %> + + <% end %> +
+ <%= render_index_document document %> +
+

+ + <%= document_actions %> +
diff --git a/spec/helpers/index_helper_spec.rb b/spec/helpers/index_helper_spec.rb new file mode 100644 index 00000000..1c08df9f --- /dev/null +++ b/spec/helpers/index_helper_spec.rb @@ -0,0 +1,61 @@ +require 'rails_helper' + +describe IndexHelper do + let(:helper) { TestingHelper.new } + let(:index_presenter) { instance_double('RTLIndexPresenter', class: RTLIndexPresenter) } + let(:document) do + { + title: 'title', + alternate_title: 'alternate_title' + } + end + before do + class TestingHelper + include IndexHelper + include ActionView::Helpers::TagHelper + include ActionView::Helpers::UrlHelper + include ActionView::Context + end + end + after do + Object.send(:remove_const, :TestingHelper) + end + + describe '#render_index_document' do + before do + allow(helper).to receive(:index_presenter).and_return(index_presenter) + allow(helper).to receive(:document_show_link_field).and_return(:title) + allow(helper).to receive(:url_for_document).and_return('link') + allow(helper).to receive(:document_link_params).and_return({}) + allow(index_presenter).to receive(:label).and_return(label) + end + + context 'when given a ltr label' do + let(:label) { 'title' } + + it 'returns a single ltr span tag' do + tag = helper.render_index_document(document) + expect(tag).to eq 'title' + end + end + + context 'when given a rtl label' do + let(:label) { 'تضيح المقال' } + + it 'returns a single rtl span tag' do + tag = helper.render_index_document(document) + expect(tag).to eq 'تضيح المقال' + end + end + + context 'when given a multivalued title' do + let(:label) { ['تضيح المقال', 'title'] } + + it 'returns multiple span tags' do + tag = helper.render_index_document(document) + expect(tag).to eq 'تضيح المقال'\ + 'title' + end + end + end +end diff --git a/spec/presenters/rtl_index_presenter_spec.rb b/spec/presenters/rtl_index_presenter_spec.rb new file mode 100644 index 00000000..7a5a865e --- /dev/null +++ b/spec/presenters/rtl_index_presenter_spec.rb @@ -0,0 +1,65 @@ +require 'rails_helper' + +RSpec.describe RTLIndexPresenter do + subject(:presenter) { described_class.new(document, double(blacklight_config: blacklight_config)) } + + let(:document) do + { + title: title, + alternate_title: alternate_title + } + end + let(:title) { ['تضيح المقال'] } + let(:alternate_title) { ['a different title'] } + let(:index_config) { double(title_field: 'title', display_title_field: '') } + let(:field_config) { double } + let(:blacklight_config) do + double( + index: index_config, + index_fields: { field: field_config } + ) + end + + before do + allow(field_config).to receive(:to_h).and_return({}) + end + + describe '#label' do + context 'when given a single-valued title' do + it 'renders as a String' do + expect(presenter.label(:title)).to eq 'تضيح المقال' + end + end + + context 'when given a multivalued title' do + let(:title) { ['تضيح المقال', 'Tawḍīḥ al-maqāl'] } + + it 'renders as an Array' do + expect(presenter.label(:title)).to be_an Array + expect(presenter.label(:title)).to include 'Tawḍīḥ al-maqāl' + end + end + + context 'when configured with a display title field' do + let(:index_config) { double(title_field: 'title', display_title_field: 'alternate_title') } + + it 'renders the display title field' do + expect(presenter.label(:title)).to eq 'a different title' + end + end + + context 'when passed a string' do + it 'renders the string as the label' do + label_value = 'a string' + expect(presenter.label(label_value)).to eq 'a string' + end + end + + context 'when passed a proc' do + it 'calls the proc' do + label_value = proc { 'a string' } + expect(presenter.label(label_value)).to eq 'a string' + end + end + end +end