From ea133a290a043f451cef848325888ae90437ce0c Mon Sep 17 00:00:00 2001 From: Mason Ballengee Date: Fri, 29 Mar 2024 17:15:05 -0400 Subject: [PATCH] Add 'Has Captions' and 'Has Transcripts' facets --- app/controllers/catalog_controller.rb | 2 ++ app/helpers/application_helper.rb | 4 +++ app/models/concerns/master_file_behavior.rb | 4 +++ app/models/concerns/media_object_behavior.rb | 8 ++++++ app/models/master_file.rb | 5 ++++ app/models/media_object.rb | 2 ++ spec/controllers/catalog_controller_spec.rb | 22 +++++++++++++++ spec/helpers/application_helper_spec.rb | 10 +++++++ spec/models/master_file_spec.rb | 14 +++++++++- spec/models/media_object_spec.rb | 29 ++++++++++++++++++++ 10 files changed, 99 insertions(+), 1 deletion(-) diff --git a/app/controllers/catalog_controller.rb b/app/controllers/catalog_controller.rb index dd9b3adb7f..be83708bda 100644 --- a/app/controllers/catalog_controller.rb +++ b/app/controllers/catalog_controller.rb @@ -88,6 +88,8 @@ class CatalogController < ApplicationController config.add_facet_field 'collection_ssim', label: 'Collection', limit: 5 config.add_facet_field 'unit_ssim', label: 'Unit', limit: 5 config.add_facet_field 'language_ssim', label: 'Language', limit: 5 + config.add_facet_field 'has_captions_bsi', label: 'Has Captions', helper_method: :display_has_caption_or_transcript + config.add_facet_field 'has_transcripts_bsi', label: 'Has Transcripts', helper_method: :display_has_caption_or_transcript # Hide these facets if not a Collection Manager config.add_facet_field 'workflow_published_sim', label: 'Published', limit: 5, if: Proc.new {|context, config, opts| Ability.new(context.current_user, context.user_session).can? :create, MediaObject}, group: "workflow" config.add_facet_field 'avalon_uploader_ssi', label: 'Created by', limit: 5, if: Proc.new {|context, config, opts| Ability.new(context.current_user, context.user_session).can? :create, MediaObject}, group: "workflow" diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 53d2e26dbc..a5f1419f36 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -104,6 +104,10 @@ def display_metadata(label, value, default=nil) content_tag(:dt, label) + contents end + def display_has_caption_or_transcript value + value = value == "true" ? 'Yes' : 'No' + end + def search_result_label item if item['title_tesi'].present? label = truncate(item['title_tesi'], length: 100) diff --git a/app/models/concerns/master_file_behavior.rb b/app/models/concerns/master_file_behavior.rb index 9423a1bac5..e4420c7b09 100644 --- a/app/models/concerns/master_file_behavior.rb +++ b/app/models/concerns/master_file_behavior.rb @@ -171,6 +171,10 @@ def supplemental_file_captions supplemental_files(tag: 'caption') end + def supplemental_file_transcripts + supplemental_files(tag: 'transcript') + end + # Supplies the route to the master_file as an rdf formatted URI # @return [String] the route as a uri # @example uri for a mf on avalon.iu.edu with a id of: avalon:1820 diff --git a/app/models/concerns/media_object_behavior.rb b/app/models/concerns/media_object_behavior.rb index 498522fbae..bc7084d779 100644 --- a/app/models/concerns/media_object_behavior.rb +++ b/app/models/concerns/media_object_behavior.rb @@ -57,6 +57,14 @@ def access_text "This item is accessible by: #{actors.join(', ')}." end + def has_captions + master_files.any? { |mf| mf.has_captions? } + end + + def has_transcripts + master_files.any? { |mf| mf.has_transcripts? } + end + # CDL methods def lending_status Checkout.active_for_media_object(id).any? ? "checked_out" : "available" diff --git a/app/models/master_file.rb b/app/models/master_file.rb index 9ffe260089..c79d4afabd 100644 --- a/app/models/master_file.rb +++ b/app/models/master_file.rb @@ -488,6 +488,10 @@ def has_captions? !captions.empty? || !supplemental_file_captions.empty? end + def has_transcripts? + supplemental_file_transcripts.present? + end + def has_waveform? !waveform.empty? end @@ -504,6 +508,7 @@ def to_solr *args super.tap do |solr_doc| solr_doc['file_size_ltsi'] = file_size if file_size.present? solr_doc['has_captions?_bs'] = has_captions? + solr_doc['has_transcripts?_bs'] = has_transcripts? solr_doc['has_waveform?_bs'] = has_waveform? solr_doc['has_poster?_bs'] = has_poster? solr_doc['has_thumbnail?_bs'] = has_thumbnail? diff --git a/app/models/media_object.rb b/app/models/media_object.rb index 09bc1c4f6f..368bb39d1e 100644 --- a/app/models/media_object.rb +++ b/app/models/media_object.rb @@ -236,6 +236,8 @@ def fill_in_solr_fields_that_need_master_files(solr_doc) solr_doc['section_id_ssim'] = ordered_master_file_ids solr_doc["other_identifier_sim"] += master_files.collect {|mf| mf.identifier.to_a }.flatten solr_doc["date_digitized_ssim"] = master_files.collect {|mf| mf.date_digitized }.compact.map {|t| Time.parse(t).strftime "%F" } + solr_doc["has_captions_bsi"] = has_captions + solr_doc["has_transcripts_bsi"] = has_transcripts solr_doc["section_label_tesim"] = section_labels solr_doc['section_physical_description_ssim'] = section_physical_descriptions solr_doc['all_comments_ssim'] = all_comments diff --git a/spec/controllers/catalog_controller_spec.rb b/spec/controllers/catalog_controller_spec.rb index 8ab264d255..d61d0664f9 100644 --- a/spec/controllers/catalog_controller_spec.rb +++ b/spec/controllers/catalog_controller_spec.rb @@ -232,6 +232,28 @@ end end + describe "facet fields" do + let(:media_object) { FactoryBot.create(:fully_searchable_media_object, :with_master_file, :with_completed_workflow, avalon_uploader: 'archivist1', governing_policies: [lease]) } + let(:lease) { FactoryBot.create(:lease, inherited_read_groups: ['ExternalGroup']) } + before(:each) do + MediaObjectIndexingJob.perform_now(media_object.id) + end + ["avalon_resource_type_ssim", "creator_ssim", "date_sim", "genre_ssim", "series_ssim", "collection_ssim", "unit_ssim", "language_ssim", "has_captions_bsi", "has_transcripts_bsi", + "workflow_published_sim", "avalon_uploader_ssi", "read_access_group_ssim", "read_access_virtual_group_ssim", "date_digitized_ssim", "date_ingested_ssim"].each do |field| + it "should facet results on #{field}" do + query = Array(media_object.to_solr(include_child_fields:true)[field]).first + # The following line is to check that the test is using a valid solr field name + # since an incorrect one will lead to an empty query resulting in a false positive below + expect(query.to_s).not_to be_empty + get :index, params: { 'f' => { field => [query] } } + expect(response).to be_successful + expect(response).to render_template('catalog/index') + expect(assigns(:response).documents.count).to eq 1 + expect(assigns(:response).documents.map(&:id)).to contain_exactly(media_object.id) + end + end + end + describe "gated discovery" do context "with bad ldap groups" do let(:ldap_groups) { ['good-group', 'bad group'] } diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index c37e0fcf3b..8f517d29e9 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -163,6 +163,16 @@ end end + describe "#display_has_caption_or_transcript" do + it "should return 'Yes' for 'true'" do + expect(helper.display_has_caption_or_transcript("true")).to eq("Yes") + end + + it "should return 'No' for 'false'" do + expect(helper.display_has_caption_or_transcript("false")).to eq("No") + end + end + describe "#pretty_time" do it 'returns a formatted time' do expect(helper.pretty_time(0)).to eq '00:00:00.000' diff --git a/spec/models/master_file_spec.rb b/spec/models/master_file_spec.rb index 488e950a4d..fadb2e023e 100644 --- a/spec/models/master_file_spec.rb +++ b/spec/models/master_file_spec.rb @@ -736,7 +736,7 @@ let(:caption_file) { FactoryBot.create(:supplemental_file, :with_caption_file, :with_caption_tag) } let(:transcript_file) { FactoryBot.create(:supplemental_file, :with_transcript_tag) } let(:master_file) { FactoryBot.create(:master_file, supplemental_files: [caption_file, transcript_file]) } - it 'has a caption' do + it 'returns only caption files' do expect(master_file.supplemental_file_captions).to_not be_empty expect(master_file.supplemental_file_captions).to all(be_kind_of(SupplementalFile)) expect(master_file.supplemental_file_captions).to_not include(transcript_file) @@ -744,6 +744,18 @@ end end + describe 'supplemental_file_transcripts' do + let(:caption_file) { FactoryBot.create(:supplemental_file, :with_caption_file, :with_caption_tag) } + let(:transcript_file) { FactoryBot.create(:supplemental_file, :with_transcript_tag) } + let(:master_file) { FactoryBot.create(:master_file, supplemental_files: [caption_file, transcript_file]) } + it 'returns only transcript files' do + expect(master_file.supplemental_file_transcripts).to_not be_empty + expect(master_file.supplemental_file_transcripts).to all(be_kind_of(SupplementalFile)) + expect(master_file.supplemental_file_transcripts).to include(transcript_file) + expect(master_file.supplemental_file_transcripts).to_not include(caption_file) + end + end + describe 'waveforms' do let(:master_file) { FactoryBot.create(:master_file) } it 'sets original_name to default value' do diff --git a/spec/models/media_object_spec.rb b/spec/models/media_object_spec.rb index ff67c818ed..dcffe4fd0c 100644 --- a/spec/models/media_object_spec.rb +++ b/spec/models/media_object_spec.rb @@ -1162,4 +1162,33 @@ expect(MediaObject.autocomplete('te', mo1.id)).to include({ id: 'Test 2', display: 'Test 2' }) end end + + describe "#has_captions" do + let(:captionless_media_object) { FactoryBot.create(:media_object, :with_master_file) } + let(:captioned_media_object) { FactoryBot.create(:media_object, master_files: [master_file1, master_file2]) } + let(:master_file1) { FactoryBot.create(:master_file) } + let(:master_file2) { FactoryBot.create(:master_file, :with_captions) } + it "returns false when child master files contain no captions" do + expect(captionless_media_object.has_captions).to be false + end + + it "returns true when any child master file contains a caption" do + expect(captioned_media_object.has_captions).to be true + end + end + + describe "#has_transcripts" do + let(:transcriptless_media_object) { FactoryBot.create(:media_object, :with_master_file) } + let(:transcript_media_object) { FactoryBot.create(:media_object, master_files: [master_file1, master_file2]) } + let(:master_file1) { FactoryBot.create(:master_file) } + let(:master_file2) { FactoryBot.create(:master_file, supplemental_files: [transcript]) } + let(:transcript) { FactoryBot.create(:supplemental_file, :with_transcript_tag) } + it "returns false when child master files contain no transcript" do + expect(transcriptless_media_object.has_transcripts).to be false + end + + it "returns true when any child master file contains a transcript" do + expect(transcript_media_object.has_transcripts).to be true + end + end end