diff --git a/app/helpers/record_helper.rb b/app/helpers/record_helper.rb index 020777e3..ba6a7274 100644 --- a/app/helpers/record_helper.rb +++ b/app/helpers/record_helper.rb @@ -139,6 +139,51 @@ def deduplicate_subjects(subjects) subjects.map { |subject| subject['value'].uniq(&:downcase) }.uniq { |values| values.map(&:downcase) } end + # Formats availability information for display. + # Expects: + # - status: a string indicating availability status + # - location: an array with three elements: [library name, location name, call number] + # - other_availability: a boolean string indicating if there is availability at other locations + def availability(status, location, other_availability) + blurb = case status.downcase + # `available` is a common status used in Alma/Primo VE for items that are not checked out and should be + # on the shelf + when 'available' + "#{icon('check')} Available in #{location(location)}" + # `check_holdings`: unclear when (or if) this is used. Bento handled this so we did too assuming it was + # meaningful + when 'check_holdings' + "#{icon('question')} May be available in #{location(location)}" + # 'unavailable' is used for items that are checked out, missing, or otherwise not on the shelf + when 'unavailable' + "#{icon('times')} Not currently available in #{location(location)}" + # Unclear if there are other statuses we should handle here. For now we log and display a generic message. + else + Rails.logger.error("Unhandled availability status: #{status.inspect}") + "#{icon('question')} Uncertain availability in #{location(location)} #{status}" + end + + blurb += ' and other locations.' if other_availability.present? + + # We are generating HTML in this helper, so we need to mark it as safe or it will be escaped in the view. + blurb.html_safe + end + + # Fontawesome helper. Currently only takes the icon name and assumes solid sharp style. + # Could be extended later to default to these styles but allow overrides if appropriate. + # Also defaults to aria-hidden true, which is probably what we want for icons used + # purely for decoration. If an icon is used in a more meaningful way, we may want to extend this helper + # to allow passing in additional aria attributes. + def icon(fa) + "" + end + + # Formats location information for availability display. + # Expects an array with three elements: [library name, location name, call number] + def location(loc) + "#{loc[:name]} #{loc[:collection]} (#{loc[:call_number]})" + end + private def render_kind_value(list) diff --git a/app/models/normalize_primo_record.rb b/app/models/normalize_primo_record.rb index 9ea61873..f0b3ea0b 100644 --- a/app/models/normalize_primo_record.rb +++ b/app/models/normalize_primo_record.rb @@ -275,12 +275,18 @@ def publisher @record['pnx']['addata']['pub'].first end + # Current logic in this method should likely move to `holdings` field def location return unless @record['delivery'] return unless @record['delivery']['bestlocation'] loc = @record['delivery']['bestlocation'] - ["#{loc['mainLocation']} #{loc['subLocation']}", loc['callNumber']] + + { + name: loc['mainLocation'], + collection: loc['subLocation'], + call_number: loc['callNumber'] + } end def subjects diff --git a/app/views/search/_result_primo.html.erb b/app/views/search/_result_primo.html.erb index cf696c47..5096b4ff 100644 --- a/app/views/search/_result_primo.html.erb +++ b/app/views/search/_result_primo.html.erb @@ -40,6 +40,9 @@ <%= link_to link['kind'].titleize, link['url'], class: 'button' %> <% end %> <% end %> + <% if result[:availability].present? %> + <%= availability(result[:availability], result[:location], result[:other_availability]) %> + <% end %> diff --git a/test/helpers/record_helper_test.rb b/test/helpers/record_helper_test.rb index cbec11b6..36c9d8ea 100644 --- a/test/helpers/record_helper_test.rb +++ b/test/helpers/record_helper_test.rb @@ -341,4 +341,28 @@ class RecordHelperTest < ActionView::TestCase subjects = [] assert_nil deduplicate_subjects(subjects) end + + test 'availability helper handles known statuses correctly' do + location = { + name: 'Main Library', + collection: 'First Floor', + call_number: 'QA76.73.R83 2023' + } + + available_blurb = availability('available', location, false) + assert_includes available_blurb, 'Available in' + assert_includes available_blurb, location(location) + + check_holdings_blurb = availability('check_holdings', location, false) + assert_includes check_holdings_blurb, 'May be available in' + assert_includes check_holdings_blurb, location(location) + + unavailable_blurb = availability('unavailable', location, false) + assert_includes unavailable_blurb, 'Not currently available in' + assert_includes unavailable_blurb, location(location) + + unknown_blurb = availability('unknown_status', location, false) + assert_includes unknown_blurb, 'Uncertain availability in' + assert_includes unknown_blurb, location(location) + end end diff --git a/test/models/normalize_primo_record_test.rb b/test/models/normalize_primo_record_test.rb index bc6ebd55..4f23d610 100644 --- a/test/models/normalize_primo_record_test.rb +++ b/test/models/normalize_primo_record_test.rb @@ -174,7 +174,7 @@ def cdi_record test 'returns best location with call number' do normalized = NormalizePrimoRecord.new(full_record, 'test').normalize - expected_location = ['Hayden Library Stacks', 'QA76.73.R83 2023'] + expected_location = { name: 'Hayden Library', collection: 'Stacks', call_number: 'QA76.73.R83 2023' } assert_equal expected_location, normalized[:location] end