From 5cbf1e363c29881315af2617364472375db591d7 Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Tue, 13 Feb 2024 10:53:30 -0500 Subject: [PATCH 01/20] update header text --- config/locales/en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index 202f66d08..397087df2 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -251,7 +251,7 @@ en: faq_link: "https://answers.library.temple.edu" resource_types_header: "More search results" research_guides_header: "Browse our Research Guides and FAQ" - digital_collections_header: "Search our Digitized Collections for unique materials held by Temple" + digital_collections_header: "Digitized Collections for unique materials held by Temple" application_name: "Library Bento Search Beta" explanation_html: "Library Search: results from %{articles}, %{journals}, and %{more}." section_heading_html: "Library Search is your gateway to discover library content. Search Everything to discover results in %{more}, %{articles}, %{databases}, %{journals}, and %{website}." From 463f5cc40f57ed248c35fc608a31bf83ea3e80eb Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Fri, 16 Feb 2024 11:37:19 -0500 Subject: [PATCH 02/20] update server_url --- config/initializers/cdm.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/initializers/cdm.rb b/config/initializers/cdm.rb index 3313bdac0..261f4bc06 100644 --- a/config/initializers/cdm.rb +++ b/config/initializers/cdm.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true CDM.configure do |config| - config.server_url = "https://server16002.contentdm.oclc.org" - config.max_recs = "1" + config.server_url = "https://digital.library.temple.edu/digital" + config.max_recs = "3" end From bddb3a2046a9b38c3c4557b115e93beba2ec7b5d Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Fri, 16 Feb 2024 12:05:03 -0500 Subject: [PATCH 03/20] move relevant cdm engine code to search controller --- app/controllers/search_controller.rb | 36 +++++++++++++++++-- app/helpers/search_helper.rb | 9 +++++ .../search/_digital_collections.html.erb | 28 +++++++++------ 3 files changed, 59 insertions(+), 14 deletions(-) diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index ce744c4ce..f75099ced 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -15,12 +15,13 @@ class SearchController < CatalogController def index @per_page = 3 if params[:q] - engines = %i(books_and_media articles databases journals library_website lib_guides cdm) + engines = %i(books_and_media articles databases journals library_website lib_guides) searcher = BentoSearch::ConcurrentSearcher.new(*engines) searcher.search(params[:q], per_page: @per_page, semantic_search_field: params[:field]) @results = process_results(searcher.results) @lib_guides_query_term = helpers.derived_lib_guides_search_term(@response) + @cdm_records = cdm_records(params[:q]) end respond_to do |format| @@ -49,15 +50,44 @@ def process_results(results) items.display_configuration = results["books_and_media"].display_configuration # Grabbing and setting @response in order to render facets. - # Merges cdm totals into the @response. + # Merges cdm records into the @response. @response = results["books_and_media"].last.custom_data @response.merge_facet(name: "format", value: "digital_collections", hits: cdm_total_items) results.merge( - "books_and_media" => items, + "books_and_media" => items ).except("cdm") else results.except("cdm") end end + + def cdm_records(query) + # binding.pry + query.gsub("/", " ") + query = ERB::Util.url_encode(query) + fields = "title!date" + format = "json" + cdm_url = "https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmQuery/all/CISOSEARCHALL^#{query}^all^and/#{fields}/sortby/3/#{format}" + results = [] + response = [] + + begin + response = JSON.load(URI.open(cdm_url)) + total_items = response.dig("pager", "total") || 0 + response["records"].each do |i| + item = OpenStruct.new + item.title = i.fetch("title") + item.date = i.fetch("date") + item.collection = i.fetch("collection") + item.link = "https://digital.library.temple.edu/digital/collection#{i["collection"]}/id/#{i["pointer"]}" + item.thumbnail = "https://digital.library.temple.edu/utils/ajaxhelper/?CISOROOT=#{i["collection"]}&CISOPTR=#{i["pointer"]}&action=2&DMSCALE=10&DMHEIGHT=340" + results << item + end + rescue StandardError => e + total_items = 0 + Honeybadger.notify("Ran into error while try to process CDM: #{e.message}") + end + results + end end diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index dfa44bf1c..7f1d4f38a 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -92,6 +92,8 @@ def bento_titleize(id) link_to "Books & Media", engine.url(self), id: "bento_" + id + "_header" elsif id == "lib_guides" link_to "Research Guides", engine.url(self), id: "bento_" + id + "_header" + elsif id == "cdm" + link_to "Digital Collections", engine.url(self), id: "bento_" + id + "_header" else link_to id.titleize , engine.url(self), id: "bento_" + id + "_header" end @@ -129,4 +131,11 @@ def engine_display_configurations [engine_id, config] }.to_h end + + def cdm_collection_name(cdm_alias) + cdm_url = "https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmGetCollectionList/json" + response = JSON.load(URI.open(cdm_url)) + collection = response.select {|collection| collection["name"] if collection["alias"] == cdm_alias} + collection.first["name"] + end end diff --git a/app/views/search/_digital_collections.html.erb b/app/views/search/_digital_collections.html.erb index 05ea4918b..84c3ad434 100644 --- a/app/views/search/_digital_collections.html.erb +++ b/app/views/search/_digital_collections.html.erb @@ -1,17 +1,23 @@ -<% format_facet = @response.aggregations["format"] %>
-

<%= t("bento.digital_collections_header") %>

+

+ <%= link_to t("bento.digital_collections_header"), "https://digital.library.temple.edu/digital/search/searchterm/#{params[:q]}/order/nosort", style: "color: #011238" %>

    - <% format_facet.items.select do |item| -%> - <% if item.value == "digital_collections" %> -
  • - <%= render_bento_format_facet_value(item) %> - <%= link_to path_for_books_and_media_facet(format_facet, item) do %> - - <% end %> -
  • - <% end %> + + <% @cdm_records.each do |cdm_record| %> +
  • + <%= link_to cdm_record.link do %> + <%= image_tag cdm_record.thumbnail %> +
    + <%= cdm_record.title %> +
    + <% end %> +

    + <%= "Date: #{cdm_record["date"]}" if cdm_record["date"].present? %> +
    <%= cdm_collection_name(cdm_record.collection) %> +

    +
  • <% end %> +
From bd34cd2190857b56d39f231c5e55fbb91cad7dc0 Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Fri, 16 Feb 2024 12:06:18 -0500 Subject: [PATCH 04/20] rubocop --- app/controllers/search_controller.rb | 3 +-- app/helpers/search_helper.rb | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index f75099ced..c2abdb6c7 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -63,7 +63,6 @@ def process_results(results) end def cdm_records(query) - # binding.pry query.gsub("/", " ") query = ERB::Util.url_encode(query) fields = "title!date" @@ -83,7 +82,7 @@ def cdm_records(query) item.link = "https://digital.library.temple.edu/digital/collection#{i["collection"]}/id/#{i["pointer"]}" item.thumbnail = "https://digital.library.temple.edu/utils/ajaxhelper/?CISOROOT=#{i["collection"]}&CISOPTR=#{i["pointer"]}&action=2&DMSCALE=10&DMHEIGHT=340" results << item - end + end rescue StandardError => e total_items = 0 Honeybadger.notify("Ran into error while try to process CDM: #{e.message}") diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index 7f1d4f38a..0ed3b3ae0 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -135,7 +135,7 @@ def engine_display_configurations def cdm_collection_name(cdm_alias) cdm_url = "https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmGetCollectionList/json" response = JSON.load(URI.open(cdm_url)) - collection = response.select {|collection| collection["name"] if collection["alias"] == cdm_alias} + collection = response.select { |collection| collection["name"] if collection["alias"] == cdm_alias } collection.first["name"] end end From a5a0a545c62aa8903bad4e59e6f5992755669aa1 Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Fri, 16 Feb 2024 13:55:00 -0500 Subject: [PATCH 05/20] move controller logic to service object --- app/controllers/search_controller.rb | 30 +----------- .../bento_search/cdm_engine_new.rb | 47 +++++++++++++++++++ app/services/application_service.rb | 7 +++ app/services/cdm_connector.rb | 37 +++++++++++++++ 4 files changed, 92 insertions(+), 29 deletions(-) create mode 100644 app/search_engines/bento_search/cdm_engine_new.rb create mode 100644 app/services/application_service.rb create mode 100644 app/services/cdm_connector.rb diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index c2abdb6c7..90c967e01 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -21,7 +21,7 @@ def index @results = process_results(searcher.results) @lib_guides_query_term = helpers.derived_lib_guides_search_term(@response) - @cdm_records = cdm_records(params[:q]) + @cdm_records = CdmConnector.call(query: params[:q]) end respond_to do |format| @@ -61,32 +61,4 @@ def process_results(results) results.except("cdm") end end - - def cdm_records(query) - query.gsub("/", " ") - query = ERB::Util.url_encode(query) - fields = "title!date" - format = "json" - cdm_url = "https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmQuery/all/CISOSEARCHALL^#{query}^all^and/#{fields}/sortby/3/#{format}" - results = [] - response = [] - - begin - response = JSON.load(URI.open(cdm_url)) - total_items = response.dig("pager", "total") || 0 - response["records"].each do |i| - item = OpenStruct.new - item.title = i.fetch("title") - item.date = i.fetch("date") - item.collection = i.fetch("collection") - item.link = "https://digital.library.temple.edu/digital/collection#{i["collection"]}/id/#{i["pointer"]}" - item.thumbnail = "https://digital.library.temple.edu/utils/ajaxhelper/?CISOROOT=#{i["collection"]}&CISOPTR=#{i["pointer"]}&action=2&DMSCALE=10&DMHEIGHT=340" - results << item - end - rescue StandardError => e - total_items = 0 - Honeybadger.notify("Ran into error while try to process CDM: #{e.message}") - end - results - end end diff --git a/app/search_engines/bento_search/cdm_engine_new.rb b/app/search_engines/bento_search/cdm_engine_new.rb new file mode 100644 index 000000000..1fc55d638 --- /dev/null +++ b/app/search_engines/bento_search/cdm_engine_new.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +module BentoSearch + class CDMEngine + # include BentoSearch::SearchEngine + + delegate :blacklight_config, to: ::SearchController + + def new(args) + query = args.fetch(:query, "").gsub("/", " ") + query = ERB::Util.url_encode(query) + fields = args.fetch(:cdm_fields) + format = args.fetch(:cdm_format) + cdm_url = "https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmQuery/all/CISOSEARCHALL^#{query}^all^and/#{fields}/sortby/3/#{format}" + results = [] + response = [] + + begin + response = JSON.load(URI.open(cdm_url)) + total_items = response.dig("results", "pager", "total") || 0 + response["records"].each do |i| + item.title = i.fetch("title") + item.abstract = i.fetch("date") + item.link = "https://digital.library.temple.edu/digital/collection#{i["collection"]}/id/#{i["pointer"]}" + item.other_links = ["https://digital.library.temple.edu/digital/api/singleitem/image/#{i["collection"]}/#{i["pointer"]}/default.jpg", + "https://digital.library.temple.edu/digital/utils/ajaxhelper/?CISOROOT=#{i["collection"]}&CISOPTR=#{i["pointer"]}&action=2&DMSCALE=6&DMHEIGHT=340"] + results << item + end + rescue StandardError => e + results.total_items = 0 + Honeybadger.notify("Ran into error while try to process CDM: #{e.message}") + end + results + end + + + def url(helper) + query = helper.params.slice(:q) + "https://digital.library.temple.edu/digital/search/searchterm/#{query}/order/nosort" + end + + def view_link(total = nil, helper) + url = url(helper) + helper.link_to "View all digital collection results", url, class: "bento-full-results" + end + end +end diff --git a/app/services/application_service.rb b/app/services/application_service.rb new file mode 100644 index 000000000..5e98dd891 --- /dev/null +++ b/app/services/application_service.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class ApplicationService + def self.call(*args) + new(*args).call + end +end diff --git a/app/services/cdm_connector.rb b/app/services/cdm_connector.rb new file mode 100644 index 000000000..41768e4bd --- /dev/null +++ b/app/services/cdm_connector.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +class CdmConnector < ApplicationService + def initialize(*args) + query = args.first[:query] + query.gsub("/", " ") + query = ERB::Util.url_encode(query) + fields = "title!date" + format = "json" + + @results = [] + + @service_url = "https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmQuery/all/CISOSEARCHALL^#{query}^all^and/#{fields}/sortby/3/#{format}" + end + + def call + begin + response = JSON.load(URI.open(@service_url)) + total_items = response.dig("pager", "total") || 0 + response["records"].each do |i| + item = OpenStruct.new + item.title = i.fetch("title") + item.date = i.fetch("date") + item.collection = i.fetch("collection") + item.link = "https://digital.library.temple.edu/digital/collection#{i["collection"]}/id/#{i["pointer"]}" + item.thumbnail = "https://digital.library.temple.edu/utils/ajaxhelper/?CISOROOT=#{i["collection"]}&CISOPTR=#{i["pointer"]}&action=2&DMSCALE=10&DMHEIGHT=340" + @results << item + end + rescue StandardError => e + total_items = 0 + Honeybadger.notify("Ran into error while try to process CDM: #{e.message}") + end + @results + end +end + + \ No newline at end of file From a5fda1942c5f1cad9d18cff229e033bf6466ac73 Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Fri, 16 Feb 2024 13:55:34 -0500 Subject: [PATCH 06/20] rubocop --- app/services/cdm_connector.rb | 2 -- config/environments/development.rb | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/services/cdm_connector.rb b/app/services/cdm_connector.rb index 41768e4bd..1e72f0735 100644 --- a/app/services/cdm_connector.rb +++ b/app/services/cdm_connector.rb @@ -33,5 +33,3 @@ def call @results end end - - \ No newline at end of file diff --git a/config/environments/development.rb b/config/environments/development.rb index 0742c0452..085398f40 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -81,7 +81,7 @@ # config.i18n.raise_on_missing_translations = true # Annotate rendered view with file names. - # config.action_view.annotate_rendered_view_with_filenames = true + config.action_view.annotate_rendered_view_with_filenames = true # Use an evented file watcher to asynchronously detect changes in source code, # routes, locales, etc. This feature depends on the listen gem. From 32751158efc8393b715449569130f18501a168eb Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Mon, 19 Feb 2024 07:43:38 -0500 Subject: [PATCH 07/20] move cdm results to bento engine --- app/controllers/search_controller.rb | 11 +++--- app/search_engines/bento_search/cdm_engine.rb | 36 ++++++++++++++---- app/views/bento_search/_item_title.html.erb | 6 ++- app/views/bento_search/_link.html.erb | 3 ++ app/views/bento_search/_std_item.html.erb | 2 +- .../search/_digital_collections.html.erb | 37 +++++++++++-------- 6 files changed, 65 insertions(+), 30 deletions(-) create mode 100644 app/views/bento_search/_link.html.erb diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 90c967e01..7608db43c 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -14,14 +14,15 @@ class SearchController < CatalogController def index @per_page = 3 + cdm_fields = "title!date" + cdm_format = "json" if params[:q] - engines = %i(books_and_media articles databases journals library_website lib_guides) + engines = %i(books_and_media articles databases journals library_website lib_guides cdm) searcher = BentoSearch::ConcurrentSearcher.new(*engines) - searcher.search(params[:q], per_page: @per_page, semantic_search_field: params[:field]) + searcher.search(params[:q], per_page: @per_page, semantic_search_field: params[:field], cdm_fields:, cdm_format:) @results = process_results(searcher.results) @lib_guides_query_term = helpers.derived_lib_guides_search_term(@response) - @cdm_records = CdmConnector.call(query: params[:q]) end respond_to do |format| @@ -56,9 +57,9 @@ def process_results(results) results.merge( "books_and_media" => items - ).except("cdm") + ) else - results.except("cdm") + results end end end diff --git a/app/search_engines/bento_search/cdm_engine.rb b/app/search_engines/bento_search/cdm_engine.rb index 4e03a0255..201505c6c 100644 --- a/app/search_engines/bento_search/cdm_engine.rb +++ b/app/search_engines/bento_search/cdm_engine.rb @@ -7,21 +7,43 @@ class CDMEngine delegate :blacklight_config, to: ::SearchController def search_implementation(args) + bento_results = BentoSearch::Results.new query = args.fetch(:query, "").gsub("/", " ") query = ERB::Util.url_encode(query) - results = BentoSearch::Results.new - response = {} + fields = args.fetch(:cdm_fields) + format = args.fetch(:cdm_format) + cdm_url = "https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmQuery/all/CISOSEARCHALL^#{query}^all^and/#{fields}/sortby/3/#{format}" + response = [] begin - response = CDM::find(query) - results.total_items = response.dig("results", "pager", "total") || 0 + response = JSON.load(URI.open(cdm_url)) + total_items = response.dig("results", "pager", "total") || 0 + response["records"].each do |i| + # binding.pry + item = BentoSearch::ResultItem.new + item.title = i.fetch("title") + item.abstract = i.fetch("date") + item.custom_data = {collection: i.fetch("collection")} + item.link = "https://digital.library.temple.edu/digital/collection/#{i["collection"]}/id/#{i["pointer"]}" + item.other_links = [{label: item.title, link: "https://digital.library.temple.edu/digital/utils/ajaxhelper/?CISOROOT=#{i["collection"].gsub("/", "")}&CISOPTR=#{i["pointer"]}&action=2&DMSCALE=6&DMHEIGHT=340"}] + bento_results << item + end rescue StandardError => e - results.total_items = 0 + bento_results.total_items = 0 Honeybadger.notify("Ran into error while try to process CDM: #{e.message}") end + bento_results + end + + + def url(helper) + query = helper.params.slice(:q) + "https://digital.library.temple.edu/digital/search/searchterm/#{query}/order/nosort" + end - results << BentoSearch::ResultItem.new(custom_data: response) - results + def view_link(total = nil, helper) + url = url(helper) + helper.link_to "View all digital collection results", url, class: "bento-full-results" end end end diff --git a/app/views/bento_search/_item_title.html.erb b/app/views/bento_search/_item_title.html.erb index 0273347a4..b7ecd355a 100644 --- a/app/views/bento_search/_item_title.html.erb +++ b/app/views/bento_search/_item_title.html.erb @@ -21,12 +21,16 @@ <% if local_assigns[:index] %> <% id_attr = item.html_id(local_assigns[:id_prefix], index) %> <%= content_tag("span", :class => "bento_index", :id => (id_attr if id_attr)) do %> - <%= index %>. + <%= index %> <% end %> <% end %> <%= link_to_unless(item.link.blank?, item.complete_title.truncate(130), item.link) %> + <% item.custom_data["records"].each do |item| #cdm api response %> + <%= cdm_record_link(item) %> + <% end if item.custom_data["records"].present? %> + <% if item.display_format.present? || item.display_language.present? %> diff --git a/app/views/bento_search/_link.html.erb b/app/views/bento_search/_link.html.erb new file mode 100644 index 000000000..5d23d22d7 --- /dev/null +++ b/app/views/bento_search/_link.html.erb @@ -0,0 +1,3 @@ +<% collection.each do |link| %> + <%= link_to link[:label], link[:link] %>
+<% end %> \ No newline at end of file diff --git a/app/views/bento_search/_std_item.html.erb b/app/views/bento_search/_std_item.html.erb index fe36bfac9..97d8e4a28 100644 --- a/app/views/bento_search/_std_item.html.erb +++ b/app/views/bento_search/_std_item.html.erb @@ -65,7 +65,7 @@ <% if item.other_links.present? %> <% end %> diff --git a/app/views/search/_digital_collections.html.erb b/app/views/search/_digital_collections.html.erb index 84c3ad434..ece30801b 100644 --- a/app/views/search/_digital_collections.html.erb +++ b/app/views/search/_digital_collections.html.erb @@ -1,23 +1,28 @@ +<% format_facet = @response.aggregations["format"] %>
-

- <%= link_to t("bento.digital_collections_header"), "https://digital.library.temple.edu/digital/search/searchterm/#{params[:q]}/order/nosort", style: "color: #011238" %>

+

<%= t("bento.digital_collections_header") %>

    - <% @cdm_records.each do |cdm_record| %> -
  • - <%= link_to cdm_record.link do %> - <%= image_tag cdm_record.thumbnail %> -
    - <%= cdm_record.title %> -
    - <% end %> -

    - <%= "Date: #{cdm_record["date"]}" if cdm_record["date"].present? %> -
    <%= cdm_collection_name(cdm_record.collection) %> -

    -
  • - <% end %> + <% format_facet.items.select do |item| -%> + <%# binding.pry %> + <% if item.value == "digital_collections" %> + <% @results["cdm"].each do |cdm_record| %> +
  • + + <%= link_to cdm_record.link do %> + <%= image_tag cdm_record.other_links.first[:link] %> +
    + <%= cdm_record.title %> +
    + <% end %> +

    + <%= "Date: #{cdm_record.abstract}" if cdm_record.abstract.present? %> +
    <%= cdm_collection_name(cdm_record.custom_data.fetch(:collection)) %> +

  • + <% end %> + <% end %> + <% end %>
From 8558ce15afcc54face7bf9adf6847e65c73d27fd Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Mon, 19 Feb 2024 09:29:06 -0500 Subject: [PATCH 08/20] abandon attempt to fit results into col-3 bento box --- app/assets/stylesheets/icons.css.erb | 10 ++++- app/helpers/search_helper.rb | 2 - app/search_engines/bento_search/cdm_engine.rb | 2 +- app/views/bento_search/_image_link.html.erb | 3 ++ app/views/bento_search/_std_item.html.erb | 36 ++++++++-------- app/views/search/_bento_results.html.erb | 2 + .../search/_digital_collections.html.erb | 43 ++++++++++--------- 7 files changed, 56 insertions(+), 42 deletions(-) create mode 100644 app/views/bento_search/_image_link.html.erb diff --git a/app/assets/stylesheets/icons.css.erb b/app/assets/stylesheets/icons.css.erb index acd2ab9b8..6e555aa52 100644 --- a/app/assets/stylesheets/icons.css.erb +++ b/app/assets/stylesheets/icons.css.erb @@ -190,7 +190,8 @@ a.facet_visual_materials, a.facet_images, span.digital_collections, a.facet_digital_collections, -span.facet_digital_collections { +span.facet_digital_collections + { background: transparent url(<%= asset_path "noun_visual_material.svg" %>) no-repeat center left; padding-left: 1.9rem; padding-top: .25rem; @@ -430,6 +431,13 @@ span.bento-guide { padding-top: 0.25rem; } +span.bento-cdm { + background: transparent url(<%= asset_path "noun_visual_material.svg" %>) no-repeat center left; + margin-left:0.3125rem !important; + padding-left: 2.5125rem; + padding-top: 0.25rem; +} + span.remove-icon { background: transparent url(<%= asset_path "icons/remove.svg" %>) no-repeat top left; padding-left: 1.25rem; diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index 0ed3b3ae0..843c541b9 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -92,8 +92,6 @@ def bento_titleize(id) link_to "Books & Media", engine.url(self), id: "bento_" + id + "_header" elsif id == "lib_guides" link_to "Research Guides", engine.url(self), id: "bento_" + id + "_header" - elsif id == "cdm" - link_to "Digital Collections", engine.url(self), id: "bento_" + id + "_header" else link_to id.titleize , engine.url(self), id: "bento_" + id + "_header" end diff --git a/app/search_engines/bento_search/cdm_engine.rb b/app/search_engines/bento_search/cdm_engine.rb index 201505c6c..273f9bc76 100644 --- a/app/search_engines/bento_search/cdm_engine.rb +++ b/app/search_engines/bento_search/cdm_engine.rb @@ -25,7 +25,7 @@ def search_implementation(args) item.abstract = i.fetch("date") item.custom_data = {collection: i.fetch("collection")} item.link = "https://digital.library.temple.edu/digital/collection/#{i["collection"]}/id/#{i["pointer"]}" - item.other_links = [{label: item.title, link: "https://digital.library.temple.edu/digital/utils/ajaxhelper/?CISOROOT=#{i["collection"].gsub("/", "")}&CISOPTR=#{i["pointer"]}&action=2&DMSCALE=6&DMHEIGHT=340"}] + item.other_links = [{label: item.title, link: "https://digital.library.temple.edu/utils/ajaxhelper/?CISOROOT=#{i["collection"].gsub("/", "")}&CISOPTR=#{i["pointer"]}&action=2&DMSCALE=6&DMHEIGHT=340"}] bento_results << item end rescue StandardError => e diff --git a/app/views/bento_search/_image_link.html.erb b/app/views/bento_search/_image_link.html.erb new file mode 100644 index 000000000..abc51af16 --- /dev/null +++ b/app/views/bento_search/_image_link.html.erb @@ -0,0 +1,3 @@ +<%= link_to collection[:item_link] do %> + <%= image_tag collection[:image_link][0][:link], class: "d-block" %> +<% end %> \ No newline at end of file diff --git a/app/views/bento_search/_std_item.html.erb b/app/views/bento_search/_std_item.html.erb index 97d8e4a28..479651fd8 100644 --- a/app/views/bento_search/_std_item.html.erb +++ b/app/views/bento_search/_std_item.html.erb @@ -17,15 +17,14 @@ %> - <% bento_decorate(item) do |item| %> <%# for debugging purposes, we'll include the vendor-specific unique_id, if we have one, in a data-unique-id attribute. %>
- <%= render :partial => "bento_search/item_title", :object => item, :as => 'item' %> + <%= render :partial => "bento_search/item_title", :object => item, :as => 'item' %>
@@ -53,7 +52,7 @@ <% if item.abstract %>

- <%= item.render_summary %> + <%= item.render_summary %>

<% end %> @@ -69,21 +68,24 @@

<% end %>
- <% if item.engine_id == "books_and_media" %> -
- <%= render partial: "fields", locals: { document: item.custom_data, document_counter: 0 } %> -
- <% end %> - <% if item.custom_data.fetch("availability_facet", []).include?("Online") %> - <%= render :partial => "blacklight_availability", :object => item, :as => 'item' %> - <% end %> + <% if item.engine_id == "books_and_media" %> +
+ <%= render partial: "fields", locals: { document: item.custom_data, document_counter: 0 } %> +
+ <% end %> + + <% if item.custom_data.fetch("availability_facet", []).include?("Online") %> + <%= render :partial => "blacklight_availability", :object => item, :as => 'item' %> + <% end %> + + <% if item.engine_id == "articles" %> +
+ <%= render partial: "fields", locals: { document: item.custom_data, document_counter: 0 } %> +
+ <%= render :partial => "primo_availability", :object => item, :as => 'item' %> + <% end %> - <% if item.engine_id == "articles" %> -
- <%= render partial: "fields", locals: { document: item.custom_data, document_counter: 0 } %> -
- <%= render :partial => "primo_availability", :object => item, :as => 'item' %> - <% end %>
+ <% end %> diff --git a/app/views/search/_bento_results.html.erb b/app/views/search/_bento_results.html.erb index 799d251dd..981d50358 100644 --- a/app/views/search/_bento_results.html.erb +++ b/app/views/search/_bento_results.html.erb @@ -4,6 +4,7 @@ <%= render :partial => "lib_guide_recommender_bento" %> <% end %> + <% unless engine_id == "cdm" %>

<%= bento_icons(engine_id) %><%= bento_titleize(engine_id) %>

<%= render :layout => "layouts/bento_box_wrapper", :locals => {:results => result } do %> @@ -17,4 +18,5 @@ <% end %> <%= render_linked_results(engine_id) %>
+ <% end %> <% end %> \ No newline at end of file diff --git a/app/views/search/_digital_collections.html.erb b/app/views/search/_digital_collections.html.erb index ece30801b..11a3831bc 100644 --- a/app/views/search/_digital_collections.html.erb +++ b/app/views/search/_digital_collections.html.erb @@ -1,28 +1,29 @@ <% format_facet = @response.aggregations["format"] %> -
-

<%= t("bento.digital_collections_header") %>

-
    +
    +

    <%= t("bento.digital_collections_header") %>

    +
      - <% format_facet.items.select do |item| -%> - <%# binding.pry %> - <% if item.value == "digital_collections" %> - <% @results["cdm"].each do |cdm_record| %> -
    • + <% format_facet.items.select do |item| -%> + <%# binding.pry %> + <% if item.value == "digital_collections" %> + <% @results["cdm"].each do |cdm_record| %> +
    • - <%= link_to cdm_record.link do %> - <%= image_tag cdm_record.other_links.first[:link] %> -
      - <%= cdm_record.title %> -
      - <% end %> -

      - <%= "Date: #{cdm_record.abstract}" if cdm_record.abstract.present? %> -
      <%= cdm_collection_name(cdm_record.custom_data.fetch(:collection)) %> - -

    • + <%= link_to cdm_record.link do %> + <%= image_tag cdm_record.other_links.first[:link] %> +
      + <%= cdm_record.title %> +
      <% end %> +

      + <%= "Date: #{cdm_record.abstract}" if cdm_record.abstract.present? %> +
      <%= cdm_collection_name(cdm_record.custom_data.fetch(:collection)) %> +

      + + <% end %> <% end %> -
    -
    + <% end %> +
+
From 55415f74cec83747394ea68c617dd634a8270e10 Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Mon, 19 Feb 2024 09:37:55 -0500 Subject: [PATCH 09/20] rubocop --- app/controllers/search_controller.rb | 2 +- app/search_engines/bento_search/cdm_engine.rb | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 7608db43c..7b84bb1d4 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -19,7 +19,7 @@ def index if params[:q] engines = %i(books_and_media articles databases journals library_website lib_guides cdm) searcher = BentoSearch::ConcurrentSearcher.new(*engines) - searcher.search(params[:q], per_page: @per_page, semantic_search_field: params[:field], cdm_fields:, cdm_format:) + searcher.search(params[:q], per_page: @per_page, semantic_search_field: params[:field], cdm_fields: cdm_fields, cdm_format: cdm_format) @results = process_results(searcher.results) @lib_guides_query_term = helpers.derived_lib_guides_search_term(@response) diff --git a/app/search_engines/bento_search/cdm_engine.rb b/app/search_engines/bento_search/cdm_engine.rb index 273f9bc76..2737ef2ba 100644 --- a/app/search_engines/bento_search/cdm_engine.rb +++ b/app/search_engines/bento_search/cdm_engine.rb @@ -19,13 +19,13 @@ def search_implementation(args) response = JSON.load(URI.open(cdm_url)) total_items = response.dig("results", "pager", "total") || 0 response["records"].each do |i| - # binding.pry + # binding.pry item = BentoSearch::ResultItem.new item.title = i.fetch("title") item.abstract = i.fetch("date") - item.custom_data = {collection: i.fetch("collection")} + item.custom_data = { collection: i.fetch("collection") } item.link = "https://digital.library.temple.edu/digital/collection/#{i["collection"]}/id/#{i["pointer"]}" - item.other_links = [{label: item.title, link: "https://digital.library.temple.edu/utils/ajaxhelper/?CISOROOT=#{i["collection"].gsub("/", "")}&CISOPTR=#{i["pointer"]}&action=2&DMSCALE=6&DMHEIGHT=340"}] + item.other_links = [{ label: item.title, link: "https://digital.library.temple.edu/utils/ajaxhelper/?CISOROOT=#{i["collection"].gsub("/", "")}&CISOPTR=#{i["pointer"]}&action=2&DMSCALE=6&DMHEIGHT=340" }] bento_results << item end rescue StandardError => e From 5343ef9cb2cdba1f171cd02cc44f088b1b1415ac Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Mon, 19 Feb 2024 09:50:19 -0500 Subject: [PATCH 10/20] reverts unsused icon style --- app/assets/stylesheets/icons.css.erb | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/app/assets/stylesheets/icons.css.erb b/app/assets/stylesheets/icons.css.erb index 6e555aa52..acd2ab9b8 100644 --- a/app/assets/stylesheets/icons.css.erb +++ b/app/assets/stylesheets/icons.css.erb @@ -190,8 +190,7 @@ a.facet_visual_materials, a.facet_images, span.digital_collections, a.facet_digital_collections, -span.facet_digital_collections - { +span.facet_digital_collections { background: transparent url(<%= asset_path "noun_visual_material.svg" %>) no-repeat center left; padding-left: 1.9rem; padding-top: .25rem; @@ -431,13 +430,6 @@ span.bento-guide { padding-top: 0.25rem; } -span.bento-cdm { - background: transparent url(<%= asset_path "noun_visual_material.svg" %>) no-repeat center left; - margin-left:0.3125rem !important; - padding-left: 2.5125rem; - padding-top: 0.25rem; -} - span.remove-icon { background: transparent url(<%= asset_path "icons/remove.svg" %>) no-repeat top left; padding-left: 1.25rem; From 9750b117a0868fc1a39aa8b766eab57e04044f4c Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Mon, 19 Feb 2024 09:53:40 -0500 Subject: [PATCH 11/20] remove pry and inadvertant file copy --- app/search_engines/bento_search/cdm_engine.rb | 1 - .../bento_search/cdm_engine_new.rb | 47 ------------------- 2 files changed, 48 deletions(-) delete mode 100644 app/search_engines/bento_search/cdm_engine_new.rb diff --git a/app/search_engines/bento_search/cdm_engine.rb b/app/search_engines/bento_search/cdm_engine.rb index 2737ef2ba..9c28c2a6b 100644 --- a/app/search_engines/bento_search/cdm_engine.rb +++ b/app/search_engines/bento_search/cdm_engine.rb @@ -19,7 +19,6 @@ def search_implementation(args) response = JSON.load(URI.open(cdm_url)) total_items = response.dig("results", "pager", "total") || 0 response["records"].each do |i| - # binding.pry item = BentoSearch::ResultItem.new item.title = i.fetch("title") item.abstract = i.fetch("date") diff --git a/app/search_engines/bento_search/cdm_engine_new.rb b/app/search_engines/bento_search/cdm_engine_new.rb deleted file mode 100644 index 1fc55d638..000000000 --- a/app/search_engines/bento_search/cdm_engine_new.rb +++ /dev/null @@ -1,47 +0,0 @@ -# frozen_string_literal: true - -module BentoSearch - class CDMEngine - # include BentoSearch::SearchEngine - - delegate :blacklight_config, to: ::SearchController - - def new(args) - query = args.fetch(:query, "").gsub("/", " ") - query = ERB::Util.url_encode(query) - fields = args.fetch(:cdm_fields) - format = args.fetch(:cdm_format) - cdm_url = "https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmQuery/all/CISOSEARCHALL^#{query}^all^and/#{fields}/sortby/3/#{format}" - results = [] - response = [] - - begin - response = JSON.load(URI.open(cdm_url)) - total_items = response.dig("results", "pager", "total") || 0 - response["records"].each do |i| - item.title = i.fetch("title") - item.abstract = i.fetch("date") - item.link = "https://digital.library.temple.edu/digital/collection#{i["collection"]}/id/#{i["pointer"]}" - item.other_links = ["https://digital.library.temple.edu/digital/api/singleitem/image/#{i["collection"]}/#{i["pointer"]}/default.jpg", - "https://digital.library.temple.edu/digital/utils/ajaxhelper/?CISOROOT=#{i["collection"]}&CISOPTR=#{i["pointer"]}&action=2&DMSCALE=6&DMHEIGHT=340"] - results << item - end - rescue StandardError => e - results.total_items = 0 - Honeybadger.notify("Ran into error while try to process CDM: #{e.message}") - end - results - end - - - def url(helper) - query = helper.params.slice(:q) - "https://digital.library.temple.edu/digital/search/searchterm/#{query}/order/nosort" - end - - def view_link(total = nil, helper) - url = url(helper) - helper.link_to "View all digital collection results", url, class: "bento-full-results" - end - end -end From 5e38410848cff740de384bac675cc14c82db70fd Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Mon, 19 Feb 2024 09:54:45 -0500 Subject: [PATCH 12/20] removes service object --- app/services/application_service.rb | 7 ------ app/services/cdm_connector.rb | 35 ----------------------------- 2 files changed, 42 deletions(-) delete mode 100644 app/services/application_service.rb delete mode 100644 app/services/cdm_connector.rb diff --git a/app/services/application_service.rb b/app/services/application_service.rb deleted file mode 100644 index 5e98dd891..000000000 --- a/app/services/application_service.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -class ApplicationService - def self.call(*args) - new(*args).call - end -end diff --git a/app/services/cdm_connector.rb b/app/services/cdm_connector.rb deleted file mode 100644 index 1e72f0735..000000000 --- a/app/services/cdm_connector.rb +++ /dev/null @@ -1,35 +0,0 @@ -# frozen_string_literal: true - -class CdmConnector < ApplicationService - def initialize(*args) - query = args.first[:query] - query.gsub("/", " ") - query = ERB::Util.url_encode(query) - fields = "title!date" - format = "json" - - @results = [] - - @service_url = "https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmQuery/all/CISOSEARCHALL^#{query}^all^and/#{fields}/sortby/3/#{format}" - end - - def call - begin - response = JSON.load(URI.open(@service_url)) - total_items = response.dig("pager", "total") || 0 - response["records"].each do |i| - item = OpenStruct.new - item.title = i.fetch("title") - item.date = i.fetch("date") - item.collection = i.fetch("collection") - item.link = "https://digital.library.temple.edu/digital/collection#{i["collection"]}/id/#{i["pointer"]}" - item.thumbnail = "https://digital.library.temple.edu/utils/ajaxhelper/?CISOROOT=#{i["collection"]}&CISOPTR=#{i["pointer"]}&action=2&DMSCALE=10&DMHEIGHT=340" - @results << item - end - rescue StandardError => e - total_items = 0 - Honeybadger.notify("Ran into error while try to process CDM: #{e.message}") - end - @results - end -end From 3a6283d413bf535b3212d3a74c6ccf18c91cf12b Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Mon, 19 Feb 2024 09:58:59 -0500 Subject: [PATCH 13/20] removes another pry --- .../search/_digital_collections.html.erb | 36 +++++++++---------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/app/views/search/_digital_collections.html.erb b/app/views/search/_digital_collections.html.erb index 11a3831bc..8fc224e7c 100644 --- a/app/views/search/_digital_collections.html.erb +++ b/app/views/search/_digital_collections.html.erb @@ -3,27 +3,23 @@

<%= t("bento.digital_collections_header") %>

    - - <% format_facet.items.select do |item| -%> - <%# binding.pry %> - <% if item.value == "digital_collections" %> - <% @results["cdm"].each do |cdm_record| %> -
  • - - <%= link_to cdm_record.link do %> - <%= image_tag cdm_record.other_links.first[:link] %> -
    - <%= cdm_record.title %> -
    - <% end %> -

    - <%= "Date: #{cdm_record.abstract}" if cdm_record.abstract.present? %> -
    <%= cdm_collection_name(cdm_record.custom_data.fetch(:collection)) %> -

    - -
  • - <% end %> + <% format_facet.items.select do |item| -%> + <% if item.value == "digital_collections" %> + <% @results["cdm"].each do |cdm_record| %> +
  • + <%= link_to cdm_record.link do %> + <%= image_tag cdm_record.other_links.first[:link] %> +
    + <%= cdm_record.title %> +
    + <% end %> +

    + <%= "Date: #{cdm_record.abstract}" if cdm_record.abstract.present? %> +
    <%= cdm_collection_name(cdm_record.custom_data.fetch(:collection)) %> +

    +
  • <% end %> <% end %> + <% end %>
From cdcf6397f74f8fe8d7780fda02e9e45ae4874da1 Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Mon, 19 Feb 2024 15:30:22 -0500 Subject: [PATCH 14/20] rubocop --- app/decorators/tul_decorator.rb | 2 +- app/helpers/search_helper.rb | 2 +- app/models/bento_search/result_item.rb | 282 ++++++++++++++++++ app/search_engines/bento_search/cdm_engine.rb | 34 ++- .../search/_digital_collections.html.erb | 8 +- 5 files changed, 315 insertions(+), 13 deletions(-) create mode 100644 app/models/bento_search/result_item.rb diff --git a/app/decorators/tul_decorator.rb b/app/decorators/tul_decorator.rb index 5178c42f4..13bd8cc08 100644 --- a/app/decorators/tul_decorator.rb +++ b/app/decorators/tul_decorator.rb @@ -5,7 +5,7 @@ class TulDecorator < BentoSearch::StandardDecorator # It's required becase we need to add a label to the publisher field. def render_source_info parts = [] - + if self.source_title.present? parts << _h.content_tag("span", self.source_title, class: "source_title") elsif self.publisher.present? diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index 843c541b9..d764fca23 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -133,7 +133,7 @@ def engine_display_configurations def cdm_collection_name(cdm_alias) cdm_url = "https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmGetCollectionList/json" response = JSON.load(URI.open(cdm_url)) - collection = response.select { |collection| collection["name"] if collection["alias"] == cdm_alias } + collection = response.select { |collection| collection["secondary_alias"] if collection["secondary_alias"] == cdm_alias } collection.first["name"] end end diff --git a/app/models/bento_search/result_item.rb b/app/models/bento_search/result_item.rb new file mode 100644 index 000000000..4cc1184d7 --- /dev/null +++ b/app/models/bento_search/result_item.rb @@ -0,0 +1,282 @@ +# frozen_string_literal: true + +require "language_list" +require "bento_search/author" +require "bento_search/link" + + +module BentoSearch + # Data object representing a single hit from a search, normalized + # with common data fields. Usually held in a BentoSearch::Results object. + # + # ANY field can be nil, clients should be aware. + # + # Each item has a field for one main link as string url, at #link (which may be nil), + # as well as array of possibly additional links (with labels and metadata) + # under #other_links. #other_links is an array of BentoSearch::Link + # objects. + class ResultItem + include ERB::Util # for html_escape for our presentational stuff + include ActionView::Helpers::OutputSafetyHelper # for safe_join + + include ::BentoSearch::Results::Serialization + + # Can initialize with a hash of key/values + def initialize(args = {}) + args.each_pair do |key, value| + send("#{key}=", value) + end + + self.authors ||= [] + self.other_links ||= [] + self.snippets ||= [] + + self.custom_data ||= {} + end + + # internal unique id for the document, from the particular + # search service it came from. May be alphanumeric. May be nil + # for engines that don't support it. + serializable_attr_accessor :unique_id + + + # If set to true, item will refuse to generate an openurl, + # returning nil from #to_openurl or #openurl_kev + serializable_attr_accessor :openurl_disabled + + + # Array (possibly empty) of BentoSearch::Link objects + # representing additional links. Often SearchEngine's themselves + # won't include any of these, but Decorators will be used + # to add them in. + attr_accessor :other_links + serializable_attr :other_links, collection_of: "BentoSearch::Link" + + # * dc.title + # * schema.org CreativeWork: 'name' + serializable_attr_accessor :title + # backwards compat, we used to have separate titles and subtitles + alias_method :complete_title, :title + + # usually a direct link to the search provider's 'native' page. + # Can be changed in actual presentation with a Decorator. + # * schema.org CreativeWork: 'url' + attr_accessor :link + serializable_attr :link + + # does the #link correspond to fulltext? true or false -- or nil + # for unknown/non-applicable. Not all engines will set. + def link_is_fulltext? + @link_is_fulltext + end + def link_is_fulltext=(v) + @link_is_fulltext = v + end + serializable_attr :link_is_fulltext + + # Our own INTERNAL controlled vocab for 'format'. + # + # Important that this be supplied by engine for maximum + # success of openurl, ris export, etc. + # + # This vocab is based on schema.org CreativeWork 'types', + # but supplemented with values we needed not present in schema.org. + # String values are last part of schema.org URLs, symbol values are custom. + # + # However, for backwards compat, values that didn't exist in schema.org + # when we started but later came to exist -- we still use our string + # values. If you actually want a schema.org url, see #schema_org_type_url + # which translates as needed. + # + # schema.org 'type' that's a sub-type of CreativeWork. + # should hold a string that, when appended to "http://schema.org/" + # is a valid schema.org type uri, that sub-types CreativeWork. Ones + # we have used: + # * Article + # * Book + # * Movie + # * MusicRecording + # * Photograph + # * SoftwareApplication + # * WebPage + # * VideoObject + # * AudioObject + # + # + # + # OR one of these symbols, sadly not covered by schema.org types: + # * :serial (magazine or journal) + # * :dissertation (dissertation or thesis) + # * :conference_paper # individual paper + # * :conference_proceedings # collected proceedings + # * :report # white paper or other report. + # * :book_item # section or exceprt from book. + # + # Note: We're re-thinking this, might allow uncontrolled + # in here instead. + serializable_attr_accessor :format + + # Translated from internal format vocab at #format. Outputs + # eg http://schema.org/Book + # Uses the @@format_to_schema_org hash for mapping from + # certain internal symbol values to schema org value, where + # possible. + # + # Can return nil if we don't know a schema.org type + def schema_org_type_url + if format.kind_of? String + "http://schema.org/#{format}" + elsif mapped = @@format_to_schema_org[format] + "http://schema.org/#{mapped}" + else + nil + end + end + @@format_to_schema_org = { + report: "Article", + } + + # uncontrolled presumably english-language format string. + # if supplied will be used in display in place of controlled + # format. + serializable_attr_accessor :format_str + + # Language of materials. Producer can set language_code to an ISO 639-1 (two + # letter) or 639-3 (three letter) language code. If you do this, you don't + # need to set language_str, it'll be automatically looked up. (Providing + # language name in English at present, i18n later maybe). + # + # Or, if you don't know the language code (or there isn't one?), you can set + # language_str manually to a presumably english user-displayable string. + # Manually set language_str will over-ride display string calculated from + # language_code. + # + # Consumers that want a language code can use #language_iso_639_1 or + # #language_iso_639_2 (either may be null), or #language_str for uncontrolled + # string. If engine just sets one of these, internals take care of filling + # out the others. r + serializable_attr_accessor :language_code + attr_writer :language_str + def language_str + (@language_str ||= nil) || language_code.try do |code| + LanguageList::LanguageInfo.find(code.dup).try do |lang_obj| + lang_obj.name + end + end + end + serializable_attr :language_str + # Returns a LanguageList gem language object-- from #language_code + # if available, otherwise from direct language_str if available and + # possible. + def language_obj + @language_obj ||= begin + lookup = self.language_code || self.language_str + LanguageList::LanguageInfo.find(lookup.dup) if lookup + end + end + + # Two letter ISO language code, or nil + def language_iso_639_1 + language_obj.try { |l| l.iso_639_1 } + end + + # Three letter ISO language code, or nil + def language_iso_639_3 + language_obj.try { |l| l.iso_639_3 } + end + + # year published. a ruby int + # PART of:. + # * schema.org CreativeWork "datePublished", year portion + # * dcterms.issued, year portion + # * prism:coverDate, year portion + # + # See also publication_date when you have a complete date + serializable_attr_accessor :year + # ruby stdlib Date object. + attr_accessor :publication_date + serializable_attr :publication_date, serializer: "Date" + + serializable_attr_accessor :volume + serializable_attr_accessor :issue + serializable_attr_accessor :start_page + serializable_attr_accessor :end_page + + # source_title is often used for journal_title (and aliased + # as #journal_title, although that may go away), but can + # also be used for other 'container' titles. Book title for + # a book chapter. Even web site or URL for a web page. + serializable_attr_accessor :source_title + alias_method :journal_title, :source_title + alias_method :'journal_title=', :'source_title=' + + + serializable_attr_accessor :issn + serializable_attr_accessor :isbn + serializable_attr_accessor :oclcnum # OCLC accession number, WorldCat. + + serializable_attr_accessor :doi + serializable_attr_accessor :pmid + + # usually used for books rather than articles + serializable_attr_accessor :publisher + + # an openurl kev-encoded context object. optional, + # only if source provides one that may be better + # than can be constructed from individual elements above + serializable_attr_accessor :openurl_kev_co + + # Short summary of item. + # Mark .html_safe if it includes html -- creator is responsible + # for making sure html is safely sanitizied and/or stripped, + # rails ActionView::Helpers::SanitizeHelper #sanitize and #strip_tags + # may be helpful. + serializable_attr_accessor :abstract + + # An ARRAY of string query-in-context snippets. Will usually + # have highlighting tags in it. Creator is responsible + # for making sure it's otherwise html-safe. + # + # Not all engines may stores Snippets array in addition to abstract, + # some may only store one or the other. Some may store both but + # with same content formatted differently (array of multiple vs + # one combined string), some engines they may be different. + attr_accessor :snippets + serializable_attr :snippets + + # An array (order matters) of BentoSearch::Author objects + # add authors to it with results.authors << Author + attr_accessor :authors + serializable_attr :authors, collection_of: "BentoSearch::Author" + + # engine-specific data not suitable for abstract API, usually + # for internal use. + serializable_attr_accessor :custom_data + + # ContentDM api results attributes + attr_accessor :cdm_date + attr_accessor :cdm_collection + attr_accessor :cdm_id + attr_accessor :cdm_record_link + attr_accessor :cdm_thumbnail_link + + # Copied over from engine configuration usually, a string + # qualified name of a decorator class. Can be nil for default. + attr_accessor :decorator + + # Copied over from engine configuration :for_display key + # by BentoSearch#search wrapper, here as a convenience t + # parameterize logic in decorators or other presentational logic, based + # on configuration, in places where logic has access to an item but + # not the overall Results obj anymore. + # + # TODO: Consider, should we just copy over the whole Results + # into a backpointing reference instead? And user cover-methods + # for it? Nice thing about the configuration has instead is it's + # easily serializable, it's just data. + # + # Although we intentionally do NOT include these in JSON serialization, ha. + attr_accessor :display_configuration + attr_accessor :engine_id + end +end diff --git a/app/search_engines/bento_search/cdm_engine.rb b/app/search_engines/bento_search/cdm_engine.rb index 9c28c2a6b..a918ac4e3 100644 --- a/app/search_engines/bento_search/cdm_engine.rb +++ b/app/search_engines/bento_search/cdm_engine.rb @@ -4,11 +4,35 @@ module BentoSearch class CDMEngine include BentoSearch::SearchEngine - delegate :blacklight_config, to: ::SearchController + delegate :blacklight_config, :search_service_class, to: ::SearchController + + def conform_to_bento_result(item) + cdm_collection = item.fetch("collection", "").gsub("/", "") + cdm_id = item.fetch("pointer") + BentoSearch::ResultItem.new( + title: item.fetch("title"), + cdm_date: item.fetch("date"), + cdm_collection: cdm_collection, + cdm_id: cdm_id, + cdm_record_link: "https://digital.library.temple.edu/digital/collection/#{cdm_collection}/id/#{cdm_id}", + cdm_thumbnail_link: image_scale(cdm_collection, cdm_id) + ) + end + + def image_scale(collection, id) + begin + image_info = JSON.load(URI.open("https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmGetImageInfo/#{collection}/#{id}/json")) + image_width = image_info["width"] + image_scale = (image_width <= 2500) ? 50 : 6 #this may take some fine tuning depending on all available sizes + rescue StandardError => e + Honeybadger.notify("Ran into error while try to process CDM image info api call: #{e.message}") + end + "https://digital.library.temple.edu/utils/ajaxhelper/?CISOROOT=#{collection}&CISOPTR=#{id}&action=2&DMSCALE=#{image_scale}&DMHEIGHT=340" + end def search_implementation(args) - bento_results = BentoSearch::Results.new query = args.fetch(:query, "").gsub("/", " ") + bento_results = BentoSearch::Results.new query = ERB::Util.url_encode(query) fields = args.fetch(:cdm_fields) format = args.fetch(:cdm_format) @@ -20,11 +44,7 @@ def search_implementation(args) total_items = response.dig("results", "pager", "total") || 0 response["records"].each do |i| item = BentoSearch::ResultItem.new - item.title = i.fetch("title") - item.abstract = i.fetch("date") - item.custom_data = { collection: i.fetch("collection") } - item.link = "https://digital.library.temple.edu/digital/collection/#{i["collection"]}/id/#{i["pointer"]}" - item.other_links = [{ label: item.title, link: "https://digital.library.temple.edu/utils/ajaxhelper/?CISOROOT=#{i["collection"].gsub("/", "")}&CISOPTR=#{i["pointer"]}&action=2&DMSCALE=6&DMHEIGHT=340" }] + item = conform_to_bento_result(i) bento_results << item end rescue StandardError => e diff --git a/app/views/search/_digital_collections.html.erb b/app/views/search/_digital_collections.html.erb index 8fc224e7c..3d7693bb6 100644 --- a/app/views/search/_digital_collections.html.erb +++ b/app/views/search/_digital_collections.html.erb @@ -7,15 +7,15 @@ <% if item.value == "digital_collections" %> <% @results["cdm"].each do |cdm_record| %>
  • - <%= link_to cdm_record.link do %> - <%= image_tag cdm_record.other_links.first[:link] %> + <%= link_to cdm_record.cdm_record_link do %> + <%= image_tag cdm_record.cdm_thumbnail_link %>
    <%= cdm_record.title %>
    <% end %>

    - <%= "Date: #{cdm_record.abstract}" if cdm_record.abstract.present? %> -
    <%= cdm_collection_name(cdm_record.custom_data.fetch(:collection)) %> + <%= "Date: #{cdm_record.cdm_date}" if cdm_record.cdm_date.present? %> +
    <%= cdm_collection_name(cdm_record.cdm_collection) %>

  • <% end %> From 568a3bce527d1827c4f992bfe1103afebdabe241 Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Tue, 20 Feb 2024 10:29:50 -0500 Subject: [PATCH 15/20] add checks for title and image --- app/decorators/tul_decorator.rb | 2 +- app/search_engines/bento_search/cdm_engine.rb | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/app/decorators/tul_decorator.rb b/app/decorators/tul_decorator.rb index 13bd8cc08..5178c42f4 100644 --- a/app/decorators/tul_decorator.rb +++ b/app/decorators/tul_decorator.rb @@ -5,7 +5,7 @@ class TulDecorator < BentoSearch::StandardDecorator # It's required becase we need to add a label to the publisher field. def render_source_info parts = [] - + if self.source_title.present? parts << _h.content_tag("span", self.source_title, class: "source_title") elsif self.publisher.present? diff --git a/app/search_engines/bento_search/cdm_engine.rb b/app/search_engines/bento_search/cdm_engine.rb index a918ac4e3..2241d570d 100644 --- a/app/search_engines/bento_search/cdm_engine.rb +++ b/app/search_engines/bento_search/cdm_engine.rb @@ -36,16 +36,18 @@ def search_implementation(args) query = ERB::Util.url_encode(query) fields = args.fetch(:cdm_fields) format = args.fetch(:cdm_format) - cdm_url = "https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmQuery/all/CISOSEARCHALL^#{query}^all^and/#{fields}/sortby/3/#{format}" + cdm_url = "https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmQuery/all/CISOSEARCHALL^#{query}^all^and/#{fields}/sortby/9/#{format}" response = [] begin response = JSON.load(URI.open(cdm_url)) - total_items = response.dig("results", "pager", "total") || 0 + total_items = response.dig("pager", "total") || 0 response["records"].each do |i| item = BentoSearch::ResultItem.new item = conform_to_bento_result(i) - bento_results << item + if (bento_results.size < 3) && (image_available?(item.cdm_thumbnail_link)) + bento_results << item unless is_int?(item.title) + end end rescue StandardError => e bento_results.total_items = 0 @@ -54,15 +56,13 @@ def search_implementation(args) bento_results end - - def url(helper) - query = helper.params.slice(:q) - "https://digital.library.temple.edu/digital/search/searchterm/#{query}/order/nosort" + def is_int?(str) + !!(str =~ /\A[-+]?[0-9]+\z/) end - def view_link(total = nil, helper) - url = url(helper) - helper.link_to "View all digital collection results", url, class: "bento-full-results" + def image_available?(link) + res = URI.open(link) + res.size > 0 end end end From 4b855337885543b03a596482ba4db428aa8ff56f Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Wed, 21 Feb 2024 08:34:48 -0500 Subject: [PATCH 16/20] add tests for engine and remove facet for cdm totals from search controller --- app/controllers/search_controller.rb | 13 +- app/search_engines/bento_search/cdm_engine.rb | 4 +- .../search/_digital_collections.html.erb | 10 +- spec/controllers/search_controller_spec.rb | 32 +- .../vcr_cassettes/bento_search_cdm.yml | 759 ++++++++++++++++++ spec/search_engines/cdm_seach_spec.rb | 39 - spec/search_engines/cdm_search_spec.rb | 54 ++ spec/spec_helper.rb | 5 +- 8 files changed, 840 insertions(+), 76 deletions(-) create mode 100644 spec/fixtures/vcr_cassettes/bento_search_cdm.yml delete mode 100644 spec/search_engines/cdm_seach_spec.rb create mode 100644 spec/search_engines/cdm_search_spec.rb diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index 7b84bb1d4..efb0835ce 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -20,7 +20,6 @@ def index engines = %i(books_and_media articles databases journals library_website lib_guides cdm) searcher = BentoSearch::ConcurrentSearcher.new(*engines) searcher.search(params[:q], per_page: @per_page, semantic_search_field: params[:field], cdm_fields: cdm_fields, cdm_format: cdm_format) - @results = process_results(searcher.results) @lib_guides_query_term = helpers.derived_lib_guides_search_term(@response) end @@ -41,7 +40,17 @@ def process_results(results) results.each_value do |result| Honeybadger.notify(result.error[:exception]) if result.failed? end - # We only care about cdm results count not bento box. + + # unless results["books_and_media"].blank? + # items = BentoSearch::Results.new(results["books_and_media"][0...-1]) + # items.engine_id = results["books_and_media"].engine_id + # items.total_items = results["books_and_media"].total_items + # items.display_configuration = results["books_and_media"].display_configuration + + # # Grabbing and setting @response in order to render facets. + # @response = results["books_and_media"].last.custom_data + + cdm_total_items = view_context.number_with_delimiter(results["cdm"]&.total_items) unless results["books_and_media"].blank? items = BentoSearch::Results.new(results["books_and_media"][0...-1]) diff --git a/app/search_engines/bento_search/cdm_engine.rb b/app/search_engines/bento_search/cdm_engine.rb index 2241d570d..111b1827b 100644 --- a/app/search_engines/bento_search/cdm_engine.rb +++ b/app/search_engines/bento_search/cdm_engine.rb @@ -41,7 +41,8 @@ def search_implementation(args) begin response = JSON.load(URI.open(cdm_url)) - total_items = response.dig("pager", "total") || 0 + bento_results.total_items = response.dig("pager", "total") || 0 + response["records"].each do |i| item = BentoSearch::ResultItem.new item = conform_to_bento_result(i) @@ -50,7 +51,6 @@ def search_implementation(args) end end rescue StandardError => e - bento_results.total_items = 0 Honeybadger.notify("Ran into error while try to process CDM: #{e.message}") end bento_results diff --git a/app/views/search/_digital_collections.html.erb b/app/views/search/_digital_collections.html.erb index 3d7693bb6..957c9d507 100644 --- a/app/views/search/_digital_collections.html.erb +++ b/app/views/search/_digital_collections.html.erb @@ -1,10 +1,10 @@ -<% format_facet = @response.aggregations["format"] %> +<%# format_facet = @response.aggregations["format"] %>

    <%= t("bento.digital_collections_header") %>

      - <% format_facet.items.select do |item| -%> - <% if item.value == "digital_collections" %> + <%# format_facet.items.select do |item| -%> + <%# if item.value == "digital_collections" %> <% @results["cdm"].each do |cdm_record| %>
    • <%= link_to cdm_record.cdm_record_link do %> @@ -19,7 +19,7 @@

    • <% end %> - <% end %> - <% end %> + <%# end %> + <%# end %>
    diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb index 1adb93b6b..583602ee6 100644 --- a/spec/controllers/search_controller_spec.rb +++ b/spec/controllers/search_controller_spec.rb @@ -5,34 +5,16 @@ RSpec.describe SearchController, type: :controller do describe "#process_results" do - let(:results) { BentoSearch::ConcurrentSearcher.new(:books_and_media, :cdm).search("foo").results } + let(:books_media_results) { BentoSearch::ConcurrentSearcher.new(:books_and_media).search("ymca").results } before { - stub_request(:get, /contentdm/) - .to_return(status: 200, - headers: { "Content-Type" => "application/json" }, - body: JSON.dump(content_dm_results)) - controller.send(:process_results, results) + controller.send(:process_results, books_media_results) } - context "content dm and regular results are present" do - - it "defines @reponse instance variable for the controller" do + context "regular results are present" do + it "defines @response instance variable for the controller" do expect(controller.instance_variable_get(:@response)).not_to be_nil end - - it "adds content-dm totals to facet" do - facet_fields = controller.instance_variable_get(:@response).facet_fields - expect(facet_fields).to include("format" => [ "digital_collections", "415" ]) - end - end - - context "only cdm results present" do - let(:results) { BentoSearch::ConcurrentSearcher.new(:cdm).search("foo").results } - - it "should still remove cdm results from bento results" do - expect(results[:cdm]).to be_nil - end end context "one or more concurrent searches fails" do @@ -49,7 +31,7 @@ def search_implementation(args) conf.engine = "BadService" end - results = BentoSearch::ConcurrentSearcher.new(:books_and_media, :cdm, :bad_service).search("foo").results + results = BentoSearch::ConcurrentSearcher.new(:books_and_media, :bad_service).search("foo").results expect { expect { controller.send(:process_results, results) }.to_not raise_error Honeybadger.flush @@ -58,8 +40,4 @@ def search_implementation(args) end end end - - def content_dm_results - { "results" => { "pager" => { "total" => "415" } } } - end end diff --git a/spec/fixtures/vcr_cassettes/bento_search_cdm.yml b/spec/fixtures/vcr_cassettes/bento_search_cdm.yml new file mode 100644 index 000000000..f1ebe2cd4 --- /dev/null +++ b/spec/fixtures/vcr_cassettes/bento_search_cdm.yml @@ -0,0 +1,759 @@ +--- +http_interactions: +- request: + method: get + uri: https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmQuery/all/CISOSEARCHALL%5Eymca%5Eall%5Eand/title!date/sortby/9/json + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Tue, 20 Feb 2024 15:37:20 GMT + Server: + - Apache + X-Content-Type-Options: + - nosniff + - nosniff + X-Xss-Protection: + - 1; mode=block + - 1; mode=block + X-Oclc-Iiif-Provider: + - cantaloupe + Access-Control-Allow-Origin: + - "*" + Vary: + - Accept-Encoding + Content-Length: + - '1605' + Content-Type: + - application/json + Cache-Control: + - max-age=0 + Expires: + - Tue, 20 Feb 2024 15:37:20 GMT + body: + encoding: ASCII-8BIT + string: '{"pager":{"start":null,"maxrecs":"9","total":1024},"records":[{"collection":"\/p15037coll3","pointer":86790,"filetype":"jp2","parentobject":-1,"title":"Spectators + and diver at YMCA Pennsylvania state championships","date":"1955-04-16","find":"86791.jp2"},{"collection":"\/p16002coll14","pointer":11524,"filetype":"jp2","parentobject":"11527","title":"004","date":"","find":"11525.jp2"},{"collection":"\/p245801coll10","pointer":355915,"filetype":"pdfpage","parentobject":"356362","title":"Assessing + English Environment Personality and its Role in Oral Proficiency - Page 62","date":"","find":"358713.pdfpage"},{"collection":"\/p245801coll10","pointer":355918,"filetype":"pdfpage","parentobject":"356362","title":"Assessing + English Environment Personality and its Role in Oral Proficiency - Page 65","date":"","find":"358716.pdfpage"},{"collection":"\/p15037coll17","pointer":384,"filetype":"jp2","parentobject":-1,"title":"Baker, + Josephine","date":"circa 1950s","find":"385.jp2"},{"collection":"\/p15037coll17","pointer":385,"filetype":"jp2","parentobject":-1,"title":"Baker, + Josephine","date":"circa 1950s","find":"386.jp2"},{"collection":"\/p15037coll17","pointer":386,"filetype":"jp2","parentobject":-1,"title":"Alexander, + Raymond Pace","date":"1951","find":"387.jp2"},{"collection":"\/p15037coll17","pointer":387,"filetype":"jp2","parentobject":-1,"title":"Frazier, + Joe, William Sharpe and Ira Davis","date":"1956","find":"388.jp2"},{"collection":"\/p15037coll17","pointer":389,"filetype":"jp2","parentobject":-1,"title":"Clayton, + Zack and Charles \"Tarzan\" Cooper","date":"1940s","find":"390.jp2"}]}' + recorded_at: Tue, 20 Feb 2024 15:37:21 GMT +- request: + method: get + uri: https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmGetImageInfo/p15037coll3/86790/json + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Tue, 20 Feb 2024 15:37:20 GMT + Server: + - Apache + X-Content-Type-Options: + - nosniff + - nosniff + X-Xss-Protection: + - 1; mode=block + - 1; mode=block + X-Oclc-Iiif-Provider: + - cantaloupe + Access-Control-Allow-Origin: + - "*" + Vary: + - Accept-Encoding + Content-Length: + - '183' + Content-Type: + - application/json + Cache-Control: + - max-age=0 + Expires: + - Tue, 20 Feb 2024 15:37:21 GMT + body: + encoding: ASCII-8BIT + string: '{"filename":"\/cdm\/sites\/16002\/data\/p15037coll3\/image\/86791.jp2","type":"jp2","width":7076,"height":5072,"title":"Spectators + and diver at YMCA Pennsylvania state championships"}' + recorded_at: Tue, 20 Feb 2024 15:37:21 GMT +- request: + method: get + uri: https://digital.library.temple.edu/utils/ajaxhelper/?CISOPTR=86790&CISOROOT=p15037coll3&DMHEIGHT=340&DMSCALE=6&action=2 + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Tue, 20 Feb 2024 15:37:21 GMT + Server: + - Apache + X-Content-Type-Options: + - nosniff + X-Xss-Protection: + - 1; mode=block + X-Oclc-Iiif-Provider: + - cantaloupe + Vary: + - X-Forwarded-Proto + Set-Cookie: + - PHPSESSID=bf856f83a7fb6bd326e73ced469179a8; path=/; HttpOnly + Expires: + - Tue, 05 Mar 2024 15:37:21 GMT + Cache-Control: + - maxage=1209600 + Pragma: + - public + Transfer-Encoding: + - chunked + Content-Type: + - image/jpeg + body: + encoding: ASCII-8BIT + string: !binary |- + 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 + recorded_at: Tue, 20 Feb 2024 15:37:21 GMT +- request: + method: get + uri: https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmGetImageInfo/p16002coll14/11524/json + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Tue, 20 Feb 2024 15:37:22 GMT + Server: + - Apache + X-Content-Type-Options: + - nosniff + - nosniff + X-Xss-Protection: + - 1; mode=block + - 1; mode=block + X-Oclc-Iiif-Provider: + - cantaloupe + Access-Control-Allow-Origin: + - "*" + Vary: + - Accept-Encoding + Content-Length: + - '126' + Content-Type: + - application/json + Cache-Control: + - max-age=0 + Expires: + - Tue, 20 Feb 2024 15:37:22 GMT + body: + encoding: ASCII-8BIT + string: '{"filename":"\/cdm\/sites\/16002\/data\/p16002coll14\/image\/11525.jp2","type":"jp2","width":3400,"height":4400,"title":"004"}' + recorded_at: Tue, 20 Feb 2024 15:37:22 GMT +- request: + method: get + uri: https://digital.library.temple.edu/utils/ajaxhelper/?CISOPTR=11524&CISOROOT=p16002coll14&DMHEIGHT=340&DMSCALE=6&action=2 + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Tue, 20 Feb 2024 15:37:22 GMT + Server: + - Apache + X-Content-Type-Options: + - nosniff + X-Xss-Protection: + - 1; mode=block + X-Oclc-Iiif-Provider: + - cantaloupe + Vary: + - X-Forwarded-Proto + Set-Cookie: + - PHPSESSID=dc31db1085edf044ead8c52bd02af9e5; path=/; HttpOnly + Expires: + - Tue, 05 Mar 2024 15:37:22 GMT + Cache-Control: + - maxage=1209600 + Pragma: + - public + Transfer-Encoding: + - chunked + Content-Type: + - image/jpeg + body: + encoding: ASCII-8BIT + string: !binary |- + /9j/4AAQSkZJRgABAQECWAJYAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9Pjv/2wBDAQoLCw4NDhwQEBw7KCIoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozv/wAARCAEIAMwDAREAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD2WgBaAEoAWgAoASgBaACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKAI3QFs0gJKYBQAlAC0AFABQAUAJQAtABQAUAFABQAUAFABQAUAJQAtABQAlACBcMSDwe1AC0ALQAUANI5pAOpgFABQAUAJQAtABQAlABQAtABQAUAFABQAUAFABQAUAFABQAUAFACUALQAUANPWgB1ABQAUAFACUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUALQAUANNADqACgAoAxtX3TXkVtHqUlo7ITtUDB9Dk0AZI1GKC0+zSa7MkkTtmRo+WG4D8hz+dADbCK5nlUQ+JGdG+WEhMliRuI574GaAJrnUvs+nm1m1p0uPMQu7x4ZVI6Y/A/nQA/TtQhRstr5mEibVDpjDEADt6/zoAha4+zb5rjxI8n2ZnDKIxkNtZensQT+FADJ7iVguzxKxikz83ljAGQDz+IFAElvf2kKTLL4m3O8SqjFcbMHqBjnOaAGxXUFteGWbxBI0Txsy71wrB+mD7H+dAEcUjXca20XiaWVyNojWMbjjjNAFm2u4bB5rSbxAZpGXylXGWRydoP4E0AMmuGm0qK7GtzoiTEbxGM8kYyPQYI/E0ANe6tzcec+vzQyC3jPzLgEEE7sdO4z6UAPsrj7ReIR4hkmEM6ZHl4U5JAX8c4/CgCOO8tYJ5AviV8SzO4ULnZk5xz2xx+NABbN9rMoh8Tu4QF2wnA9TQBcs9csbSIrca6tyzSbg5TGFx0+nH60AVLudJoTIniGfYZDGXRPlU9ce3GKAHR6naxiVZPEhmMwCJ8v+rPXNAF/Sp4rq5gEWsi7kt42V1xjfuYHJ+gXH50Ab1ABQA09aQDqYBQAUAZ+p2t3Nsks3iDrxiRQf1waAM+a01t4omW303zAT5gIO1h+WfSgCOX+19yNp39nvGwUZB4jYockEevGOvX0PABKYdVeO4aZNNec7fLznC8fNnjPXpQANbanG8TRCwdAgBLjGW4yeB9aAI72LUorqVoJNOeKWQgJcYHZcdBknd5nfoRQBYs47htkeoLYRc5QQc5x1GGH05FAF/7Pp0jlfKgZkAJGBkCgAxpzwlsW7RxsVJ4IUjqPqMfpQA+GKyEmYUh3r/cAyKAGrHp8s7hFgaVG+bGCQevNABu09H+z5gVifuZGT17fg35GgB7QWZALRxEYwCQOlADYlsdzpEIdyEFwuOO4zQBCiaRDCNotVjRzHn5cBh1H1oAfK+mWW3zWt4fN+Vd2F3e3vQBHFb6QjsscdqGZgWA29T0/E0ASLLpvmvaq9vvTl48jI6dR+I/MUANWLSomCKtqrOSwHy8nvQBNEllvDQiHdzgpjPoaALFAC0ANPWgB1ABQAlAFHUL27tWUW1hJcggksrDj2xQBnHXNQaJY5dCud0mQQrCgCCCFW2WC+H5ord5kd2Mh2jHAIwe21eOlACTadbXtxe3M2gk3SPlWZz+9GcAgZ9AKAEmj3WX2U+HJmt4ySIw2AxJ+v49aAK1ppWnSTmKbw5cRBiTvaRs4OT0B6A4H4j3oAtXdusR+xnw49zbW7nyNjHHI5JyfUmgBbcJb2V448PvCJdqGAMd0meD9OtAFeaMTWdvaP4auPssUrMsIkxgkHk+3zt36igAjEmmyLPaeHJ4Rgk7ZDx/nFAE7JDFc2+ox+HZ3uZT5hYMcoST2Jx3JoAgmsLRY47qbwzI8krM0gRz8nzHGRnuOaAHGZdQt0hbwrM0duu2LeQAvy9BzmgCf7IthJNHbaAzwzwBHEch+YHqDk4/iP5GgAMEcujRRP4dm2JMQtvvOVBBJbOenzEUAPNvGdKKf2HtEB/dwGTO4NjdjB/nQBDFYWdvaJfQ+HmW4ikGyISHcoBzu6+tADbmBLpzdz+F5HmkOSGl5JwOwP+yBQBXeyt5ZAW8JSbiDnMpHr6GgDTi02Cy1S2Wx0jyw4BkuBIfkHUjr6oo9OaAOgoAKAENAC0AFABQBz2vXEMWowpNNexqYmYfZ+nBHX3oAxjdWaCQ/bdYBb5+YyPpQBLDfQaVfKy3epTiNDmFoiykkKQM/T+tAE2oajaS3t1G39oQy+YFBiUkNgYyD2FAFU30NncmMyas7xzBO5DdDnPpx+tAGlez2FhcyNLcX0r3qKytGpYIu8nAI6dfyoAp2zW0swja71YGSLzFBzjAyOvrx+tADFvbcaRdyRy6oWEiO52/OOdoAPcUgITe2AgaN59XLM6bn2EkbNwHPcHr+VMBzXlhcBEF1q+7ABBU4B470AXr63GkXVvPJc391ED5pAbI4ZR0/4EP1oAgvHt3eF1n1QR3LtINg5UljgY+oP6UAIk8FlJaXQvNTeJmLFGjJ3Y4wR2oAab6xLN/pGrgdvlJzkE/5+lAFnUbm2lnjuTPqiJOu5RGp+X+HGO3Qn8aAKl3bWFqXje51XcODtUn360ALBqemR+cJZ9UPnRGANKh43Ec+xyaAJLi809ZEtZZdVL2rSJ5qock59e/tQBX+0ac0hkN3rCuTnPlk47UAa1ndwajq9sfMv45ol24aPakm3PX65oA6SgBaAEoAWgBKAFoAxtZuWiuURNVhsj5ZOJogQeeDk/yoAz59SjmMKQ+ILWOaND5jlBsf9cUALKuppd20Euv2/nSPlY0thlhtPYdsAnJ4/SgCSDUAdKMQ1y0+1b2/fSKOm4kgqT25H4UAFu91LbzyJ4gs5XUKTII1KxgdTgHHPrQBVFzcI8kn/CSwSJHE8riOEPsVQoJ4zjB7e5x3oAs2moxLNJJP4htJA0ZWNCFTYc8EjPbpzQAlxqDGGJYfENikmwK5EatubPXGenIoASW11aOAX8mvQC3RA5dbcbSuDzwffP5UAQ3JvIropL4ktYXVFO1ogoOe/UA9DQBY1C6Nyjy2muxxrAixylU3jcxwDx7kfTFAEMUlzKkdvH4ptHmwAoEaknGPfJ6GgC1Yai0+n3MD6tZvdoTtk2gbQAOSpxQBWivmj8x5/EdpKShjQpGAquSMMcHBxkfnQBWj1S9mljVfEdiEZchnhCnAzng9DyvGfU9qANAXkkemtPLrcDNOQIpWhG0YODx3HvQBSkurhYtz+JbCRQwOPIU/xAc4PAyRz2oAsTXM8thazjXrWF4sJcOgDozkjGTwB36+tAD7m4mmWGW1162hUqYizxAq7g8kZOO4oAZaS3H9prbyeIoZHWYFofKCluTlQc89CMCgDqKACgBKQBTAKAFoAwtaWV76MJYWN2ChwtwVDZ9if880AZ7W2oB1aPw9pa4zuG6PJ/HtQBe867ks0uhpdomoCQxxrIwBVQGwQcenb0JoAJ7N1mgWHRrC43IvnSEIpB74FADNRtbu1mMOm22nNFP96KRQuV5yMZwecdvWgAW1nt7COUaXp6ysZFuEVUC7CG2jPudmaAKscd/cStM+haVIHwQ25Mg55yec0ATw2kl0lyZdD0xHC4ibCPvb34oAdv1S3RrU6bYm0Vzgl1QKvB5UZ75oAms7W4nkIv8ATbOHbtCMEV/kx932waAK11a3kU80On6TpexicjC5YDlSw470ATXCukqvZaTp8lwihpSWRWRyM4zj9aAIrRLwSkjRtNjLnbIUZckdxwOaALP2GFNVlE+laeLNV3Ccqm4HAzkY+vPsKAM62tb5GhS40XTN+FLlRGDjPO0fT9c9aANDUoWWSGG1s9PkjVcfZ5gqlSfT/wDV2oAz3W9Ns+3QtKVAGyd6EKcDkjHqP0FAEgTVpIGjj0fTCrDIUMpGexx370AWrJbhp1iv9HsYLdSSrK6NhiR0GO9AEUYv5NUDDR9PjZZl3TB0aQLuOT65xmgDpKACgBKAFoAKACgDn9ctIrjUoTLYzThYm+eJsEcjj/PpQBjyx2DShf7I1NXfIADkA0AOtrG1maBJNIvldpcEtKcJyAT+RP5GgC3CkelaizwafqD+VlBtbcrjjnn6H8qADUb77ZMjy6FeSOBhSONo+9z+IAoAmtntYtKvY20y8jiiCykSElnI/u/TaKAK1tYWdzco/wDZN8glcsWMuFGc8kfh+tACW6W1ldedHo2o70fKnfkE8jOKACytLfVbqU32m3Vu824nMh284zx9WP5UAPurktfQ/wDEnvnS0wkbByMgcZx36CgCKS4tv7YjuRo18LlnDHnAxnrx160AGo21rPqF050fUPNaQ7pImwH2jaD+X86AJY9Ltbe7haDS7kHy/NZjKcKcZ2/XPFAEckUeqXge50e9V5jskPmYUZ4/LFAD7429zeNLLot+0kI8tWRsBgCQP50ALcNFqMqz3WhXnmrjBDY4HSgCG503T7dmhXRr+RD8p2ycEcDpQA7T3hsJxNFol+svT724Y5H8qAHw2dubmO5fSr3fJcE8yZ24bgkelAEtktnca2twmmXkcryk+azYQn5jnHfv+dAHUUAFACGgBaACgAoA5/xBNax3ERn1eeyZRuVYgT+PSgDJGqaas8JbX72Xy5M7iODj+h6UAS2dzbXksMFt4ivnaYkBcY24TdySOwU/iaAGz6jpt5Iy/wDCRXkYGPkCt842qQRgdO/4mgAS4sLofYz4hvTIZAi7gw55x2wAcjk+lADDfWvnSW7+JLvzBIse2RO4YNlcDrwRk+/HSgBwvrCA3No/iW8WQPtJIOVKnkjA/CgCCKawgYynxHfQiQHEjLgNhsenqKALQubJ7AE+IbwItyUeQjljsBAPGcYXP40ANQWq3y6f/wAJFfCZQI14+90IGcfSgBL3U7NrnypNdv4SFCMgUY9CT+YNAD72Wxt52hm8SXiBCE8oKSARgY4X/ZP60APt57DU71ltdfvHkHyMqIwA7gE7cdj3oAq2+p6ez20p12/Co/3GUfLgkc47HpxQBPPq2nB5zF4iuIvOZXCGNhtBIb5eB1B/I0ANsxYX93GkXiO7a4ySA3BOOOuMfrQBs3mi389wZIdZuYUJBKA9OR0/AH8x+IBG/hy5dlZ9bvWKggEsP8KAJxotz9laE6xeFi+8SFhuHGMdOlACxaLLFqP2salclS25oiw2nknH6/oKANagAoAQ0ALQAlAC0AVp7uzhmSKeWNZH+6rEZP8AnFAFe5urR7adILqCOYKyqzEfK2OP6UAZcTa5uIgu9NeONATIwJPfOcfSgCNn1gSeYNR07y0JYheSRk9cj09DQBLfXl8HNxp15p7QsBsVwSxbafTp0NADGudWCM7ajpIdRnGGx0br+O39aABrnU1jDvqWlh2kAGM7SDnj1znH5UAOudRuw8og1LSxsZQFcN8oJ4yc+uKAIBPrkmVa/wBLhCOPu/xjH48Zz6UASibWnlVhqOk7umBuOePz60AXpri6gsFjubmxgvdygM2SjZOOnBFAFC3udU23T/2hYXTC3Dxr02kk4Y9OMcH6CgBDc6sbf7TDd6VIY1LMdpBXnB70AS+bqcywtBqWm+aVKlcHaxJOCO/p39aAB769mlkktL3TRbgDyzJ1bgZPB45zQBJDdX7SvEb7TvNCfIgBBDHpnn+VAFZ7vVpWkhbWdPik2FVEWeG3IcnIP8OR/wAC/IAS1vNUt7+OC71qxf8AjZCDkoR24HoaAJjdaxcSMtvqmm7ZD8mM7gO2KAJ0vL5Lq0MuoWRQ7Y54/wCIuSR8uPqB+FAG7QAUAIaQC0wCgApAYOu20k15Cw0mK8jA+ZnbBHWmBTu7IyXLsnhyC4VhnzPMxk4oAsRWcllErWuhwq7BkkRXwCu4AfXILH8KAIrayk+1KG8OwwxuAruH6LjpigCL7HPhoR4ehhjL5LCfbu6gfzoAqHR2Z3x4bRivGRN7cfpigCcaCg0+WT+wlWfdhY/O4I55z+VACDRI47lIP7ISSJghMgkwFPGfyy35UAF1ogZZo4dBV4huWNllALDsR+ZoAqnRJESEjw/tkXB3CfGWFAG9awx6vv8A7U0hYZExGpk53DrgH60AZZsL2zhKnR7MmRWiIVyAV4OOvdi35UAPltZbYzx23h622OFXeZBznBKmgB8MVxHieLw9bR+XtZX3gkEHnn2FAEEdrNNGWk8NW7rxtxJ0GAMZz6D9KALVpAz3kL3GgxKVwfMRwSvoQKAC709IbhvK8OQSpuwHMmM80APit5LydFvdCgQZUHL5KgDAP4ZagCrFbSCXzrbw1EjxN8khfng4/lQBLpdmWv0aXQYImEu8yrJkrySDjP0/OgDqaAFoASgAoAWgAoAwddFnJdxR3FvfyOU4NsDt69+cZoApSLZ2dhbolpqjIwYhMEEB8g5/w7UAJFHYnTbqUw6uFXZvU7gzZc/dGeeTz7YoAzImsHu/LCay5zymSCoOACe/Y/nQBpSQ6daXTr9k1V/JYNlVLKxDA5HPPNAFKGXSNQuzBaDUi8vDSKwbYxGwEjJ+uT6DqaALN+beG1Wwks9VkELsfMRSu49O3UYoAI7bTdJnNy/9pzSJIFUbM7tysQAON2BmgBkR0q2kNuLbWS6Bfl2k7QCQOh6Eg89DigAk+w3F6ZJLTWEd5AR8pKgk/XAH40AW7kWtzLdNJb6mEhdH3KrZLDK/KPTHX60AUxZaZLZG5+z6u/kuNqS5DFsf/W60APim0q3ltA0Gp71YyRpIRliOp2lsn8qAI4oNJuJ44Vt9aj3uEAKEKueMnnGPWgC5bw2mnpcPb2upSNb7o/LfOHGSvy+vqKAKCy29koaHSdVkaWHaxBJKdsE4oAuXVtp8NpBHPb6s25fOGwM7ITg4J7EFB/nNAElrp1lqsYlK6lbmICPDFlLDLYJ9epz9aAIEutNjgayNrq5Tz92TGRznk7s9PrQBNptpZWWpWTWkOoM06ggyk7EXa33u2eOnuKAOpoAWgBKACgBaACgDA1ubZqMIGtnTyq52GMMr9R34oApTX8trpodvEZdp23RSLaKTt5zhR16daAGxyyXNwY7fxY2Z3+VfIU44UbQex5Hp60AWILkizmhXXjvhkG6cxhgMk/Lz34Pc0ARpeELIT4nEhCgjFunyjcBnH44oAerMlvbSxa5JMyySxuyR58xm+fGOQNoBx+XGaAKt1qEEtwby08SvbrIN4jMe8DoMAE9f/r0APWZ7h5Hj8VgCNdxHkr8ozjnn1P8A+ugB11qSXNyZIPFEdvGY1+T7OpIO0nOSep64oAYbhbqSCO28WbSNiqojBLEDHPPOffNAEqX0lyv2CLxEY7pZSGd7ZctnICgdOMUAMa7iiLWt14iczi4YElCg+6Rjg9PQ5xmgCIzE2wK+K2kZI8ErCCSMgZ4Pv1pAPs9WH2WZpPEwdnTEYNsqtGc5zjPPAPWmAx7y9Mc9wviQm3idEJS1DNkj0xwCTx1oAfFfMrKj+KCMkjBt1Hv1OfWgDQu7+G+0wfZtYEcsBRnliTOcggfLnoeuOelAGTc619pu4raHxC8PAjfFryXHGfbJ560AX7S4bVIYbaHW5WdHPmOINhkAI4z2/D1oASK9RNa3J4i8xHnCfZRGG6sQFznjrjPtQB01AC0AJQAtACUALQBjaut8byJrZLJ0A+YT4B7/AP1qAKMx1Fbt0hGmPEFBjRyBs9f1oASGe+SYLPFpUKrkb1YEqxHyfmVH4D2oAdINV3bII9OKfKzbmXLHvnH40AP04XMkss12NPEDKSskW0lT2oArMNaWGIpcabKu7e4O0Ke/8uM0AT2EV/PMBJbaY9u43L5eCQCB0GPWgBIrTXYF2rYac+RhiQFJ556CgB8NlqxlQS6fpsab13lFBOMjd29M0ATxWeoJfRg2Oni3D/MyrhgOcY469KAK0VnrkbKxtNPMgfLSbRkjJ6cemKAJrWy1N5j9ustPKHLZVQTkgnHT1/nQBWTTtcW4kbyrAQlQEURLkHHP64oAtvpd4sqyxx2oA27oxEuD2PP4/wA6AJrqC/jaE6daWioyHzkcAYbjHQc45oAh+yaqSS1lppbOc7ev6UASSWt+2kyLHa2kd4do4A2HH+H9KAIWg1VYYtmm2Hnl/mIHyquOucdc0AMWHX4pnkjs9PHPy7eD0+n0oAfa2mqLfRtLYWCxFgzsgG5eB049c80Ab1AC0AJQAtABQAlAFS90qy1AhrqBXYKVB6EA0AUz4a0iEGRLIMyjIG4845x19aAMs20EOllpPDk2+SREaFXzk7SM5GeBuYc+tADIkSK9Yp4XnSUoxJ8zgg+hxjn04oAZBFyY4vC8qwOwyTJzkZ/x/wD10ASR6ciWrXCeHXDidUEPmfMUAU7s5x94fpQA6zSTT5lltfDM0eAQAs4yOnXt/wDqoA14NUvpbaSR9HmikVgFjaQHdk8nI9KAKo1/UWLBfD90SpAP7xRg4BI/DPbigCSDV9UeZFm0aWJC+GfcGwv0FAEs+q6hFNKseizyxoSA4kUb/oKAIE1vVfLj36Bcbyvz4kUYP+FAEp1PVBDHIdKfJLbkDAkY6dx+dAEba3qasAdAuGB7rKp/pQArazqSLE50WbDpllDjKNkjBP4D86AFXWdSMu1tCnA3hd3mrjGev9aAJp9Sv4rhoo9JkkXcAsglUAg9/Uf/AFqAGz6nqKLatFpEj+aCZVMgBj9AaAEh1bUZJED6JNEr5+ZpVO3juB+VACWerahPcJFPo00KEgGQyLgdecfgPz/MA16AFoASgBaACgAoA5zxAbRdRge4nv4WVchrcnaOo7fWgCnd6ppl0zv9t1aHaoUeUXAOB1xjrQBLcyWdjbSWMk+orE9zuMqtlgWXfj1K8+/NAFa5u9JeWD/SNStjbL5Y8sFcBcr6d/agCxevYsV1KKXUAJlCl4eCMYTnIz/Fn8PwoApTCxx+91jWGgdCCjByTkL7YxgjjFAFzSW019Qt1gv9RlMYLIkwOzH4j2oAgn/srVNWQx3moec82RtXCocdQSOB8tAEmmtBPvNvqOsSSxAyCOVz82Mfhzxx/wDXoAW/1Cxv2hupJdTtpY0O1IgVJGcZ6UATyf2dqSNdsl2rxwB1wPmYIxIIP97P40AUbe60iztbZIJ7+NoXUqfK+bjK/MccjG7j0PHagCxNPpmsXFxPFJfCVGjRmC7Np5wVLDj3xSApNJpvl+a1/rCFQS3JbDA9ehyeOtMC9byabewf2eb2/mlSVpgZclgVHTJGMcdKAKaTWKGKR9Q1pJJFGdzEkDqM4HNAFuLUtPtLxXXUNUfbhSsu5lHAPII5JCke26gC9Z2trdTvrNrfXpDfM0O8qDgngqfxoAylvNMeRibzVLYux+RcqST6lRk8+poAuQQQwanZRpqmrTPKVdUeQlduGPzZHTg8fSgDqKAEoAKQC0wCgAoAwtZnmTUI1i1aGz2puKSrkMOR/n6UAQpfSfZHVtds2lY5RwvAGP8AHFADLlr+MQzza5bpbSONjeXjcMk9fpQAs2plLIKuu2fm+Zkvsz8uOmP60AVpLm/kAK+IbQCN+W8ohfu9M/iDQAPd38F2beTXbdXIEmHhONuB39P/AK9AFqXVEea326vHsgAa4WNDmTGMkH0oArpezmFpYddg2BGk+aMliApOcfh+lACvdajbORPr9kpQZZfKO7pnp+IoAfdT3N7eSRWmvQxsrfLH5fIGOnvyKAHXF7O7BV1y0gUIoZXXDbsjOc9M8igCeGSdrW4VtXicLFxKEwEO45yfpgetAFNrm5Kr5WtRRpIzNGzxkggHB574oAikv7y2TcfENmV56Rlm5z/9agDVhkmvbm4ubXVYHhER8tFXOwnGC3r0NAGdBd3JYk+I7MqTzlOeOuPwoAsTX1w0UZh1m1XDCFnMWQZNpb+WPyoAha5vlkEMviC0VpI96YjwCD0P50AWGvW+zmCTWrRbhXO4mPjb6YoAksL90uo0n1W1uRI2wIi4IOT0/NR+dAG9QAUAJQAtABQAUAZGq211LeRPb6faXChTmSb7y+gFAGVINZaQwL4etBnGXJXacfjn9KALt1Z30+nwwjTLLcZGLhjlYxnAIHc4zQBFDpM8eoSRHSLH7GzcPj5gM9cd+1AEUmnaxHAYl0/T5g0hJA+UYxj060AWok1S4ZxfaRZhBERkNuLEZwv05/nQBXig1hQsyaJp8TkYKhuSD2JoAnW1vRZySto9o14WMe3ICmM9s/TigCvJYanOk80mjaf9ocKFzhudpySe/IUfT1xQAqW+sJdNcLolgrkDa4k5B70AJcaVfyyRY0yxzIyvcSuAxJJ+bAP40AXEg1GOO7tFsLTySJGi9H5+UEe46/SgCHyNXfTHhbTLISIcRLkbcE8nH9KAKx0/UWKFtA01m4BJI4HGf0oAkEGtW+1rbR7GIkEOEbnHp+fNAEsdldtDBt0ayh8xv32cEqucdPpQA63sr43UltNplmlm0u9XQ4KnbgHHr05oAqrYauZYhNpdjMEVVDtgFVAPHHpQAkmnaq0olOk6fI0kR8zIGQ/9R0oAu6XYTC+eW90m1hIw0ckWCVOOf1HWgDeoASgAoAWgAoAKAEoAMigAoAMj1oAKADIoAKACgBaACgAoASgBaACgAoAKACgBKACgBaACgAoAQ0gFpgJQAtAGRqekXV7fRXVvfPb+WhXavQ5oAqy6DqUiMq6vIu45PegCd9J1CT7IH1AlbfbuHI80gg5P5UAU38NaifMKavIu+RpAOSFJOcfQUASWuh6vBLFLJrLvsbc6Y+V/agCSTRNRlS6RtSO2eRXUcjy8PuwPr0oArHw9rTTbv7dcKo+XC8jNAGlpOl3djLJJdX73RdQo3cYxn/GgDUoAKAFoAKACgAoASgAoAWgAoAKACgAoAKAGmkA6mAUAFAFea+tLaQRz3MUTEZAdwufzoAhuL63nt3itb+3WeVSsREin5iDj/GgDn5r7WIQwGraf5MJHmSs3KkAHBOOcgN0oAspe6pE6Ndatp+HDKmwHaWx3Pt160ANm1DVYot41XS2wwBIYcZIHP5//AKqAHC+1BGvIJdXsFukWIKrDaqHktnPXII/KgBYNRvo5z9r1jTNqKcqnBJIOPryO1ACiTVJrQNBrVk0qMZJWyNqrkYHsMA0AEl9dloV/tmwUpHulK8gkEq34ZZB9c0AAvL3+zLUx6zZGQn95KxyGzyB7fjQAWlxfqt0za3YTZiLR/OMIeACfagBLe51WZJJ/7W05wImKheAMkYLfhkfjQBWOo6oIYXk1ixiaTJUbThucHnHPNAFiO+1FRL5usaYZGUJEFf5Q3ct+ANADPtWuvGX/ALT0sQ4wJg/BPJP5DFAEwu9TiV7d9V043RcOu48BCP8AGgCNrvWPnVtU01djYyQUGQwyMng9CDjv+VADrS+v2mja51nTjEjZlEbAEj2z25FADpTrTj7XBqlm9uhJYomRtB6cZ7UALY395c6t8mqWcts7n91tIcAZ4HA5wV6+maAOhoAKAGE80gH0wEoAWgDD1u1E86n+yIL4+WfmeUKw9ufrQBBa2CWl7aGHRLeMOoMrhxujIzjn+Lj+dAFbF09jLHH4Yt44nJYq8oUZwRkjA7UAWZ4ZIXjtbfQLeaFU3AiULtJHzcUAV/scjsc+FbYb1O4mZenXHT1AoAlvYJTqRlj8P2t0JEG5zIoZjt2nOeoA+X/9dAD20uE3Uhbw/abdhcS7hy2OQR9c80AQ2sEsGnXG/wAOWyO6qhjicYmBbGOOgAOaAGx200SuI/C9rFuUKT5y4OSOOB26/hQA+1sJGsJYbjQLRQoVliVhtd+59qAIo3vbK3k2+GYB8v7zyph82DkcAE9efxoAt2toRYXDL4ftY3kCDy/MGJFz3OO1AEF2JhAkcnhq3mSMEKiyg7BnsMfyoAbaWLT6eWm8OWpeMgRxrIMEEnJ56dT+ZoAdPbMlnaxL4etCjMzzQmQfI3QYPuB+lAC30UrXKiHw9BLKkabZHcDacdBnGcUARzw3txBJ9p8N20khJK5cYBPU/nyemaAH3emJFcF4dAtLiFol53hSWOcjPpgCgDR0lGFpLDcabHYxtwEDhlIPFAFHTrOeLVkabRrUENn7RGQDHwe2T6D86AOmoASgBp60gH0wCgAoA5vxCludRi861vHynMlsxGBzxxQBUtrXTbpyoh1ZCqMdzlhkAdM0ASeTbzaQsDW1/wCQ8z/ekO8gLjn684FAEU13psuoC7NnqqSDHCIwXHHb04FAFiFLLUbqXYmpxMVZ23blB46D86AGRw6bdtBbGHUojAkhDnK8N8xye/K0AV7a6sYY2mtrTVZ96bdspYgq3fn60AMhhtJoWRLXVkKws5BkYcr/AAg++f0pAWMWVtpLFLbU5Y7iQIwLkuu05yPTr+lMCKeKzg8lBbas8csTNvEjblwcYPuaAK8kFk0BcwazG+VDgFmz7e/3aALd5craxNpK2N88cMgKTIT824bvyG7H4UAOfSbFdRulSPU2aJC7OZWCnvhfWgBdGuodPmCR2t7FEzEN5zFgOvPT/Zz/AMCoAbfafpsep/ZZINRbK48xGZl65A/8eP5UAJfS2s83lS2epBrQ+UjxsfmXu2aAJitjqd/FGy6rEZF2jO5UwoI5/L+VAENtZadN/o4j1NQobhmbChd2MfUDj6ikA+VoDpcM5tL+RIZTsj3EM+CDkj0pgWNIgt7vVDfCG8t2di4WRyAxy+QV9ufzFAHS0AFADTQA6gAoAKAM3ULG/up0e21JrVAMFFQHJz15oApz6bqFta7zrE3lwxZYLHlmwck9fwxQBnxa7ape280usyiPywrxvDxIclNxI6fNQBXjMEUUV8fFFwYnIj+4SNwVc5646Z/GgC1qV07u9wmvyJaOofEUGQiFtoOevX0oAq309lPcNcx+JplRTkxxqxGCx6/qP8igC1dSr50cNnrkqtZ22ZAibhgL1PIGSCKAK7avGEh3eJHjCx7XHlHeWOeW7DGVoAkgdNQvYorLxPK8m0scRjBIJ+n9/wDSgCSS9t/7PkWLX5ZZbZy0rRpknLYHB9/Q0AVri6jZTC3i1owwBKtEdwx7/hQBO2rwyQR20fiLypY97PKYtwZcnA/AfyoAlM/k2FtNJ4kaJJt2HeIYfk9PSgBLa7D210f+Ej8x9oYSeQQEUHJwDwchgPyoAppexJE12PFJLyop5iJA4PbOO3/jpoA0NM1y3tlb7drsF47MAERORk4GKANabW9Mt52hlvIkkXGVJ5GcY/mKACXXNLgjiklvI0WZN8ec/MvqPzoAhTxNo0jbFvoixYKAMkkk4GKAJo9c02S/Nktyv2gMUCEEEnkHHr900AX6ACgBD1pAOpgFABQBlahJerfItpdwJ+7JaKXHPI59eme/pQBU+1a+JlieXTA5HzJluB6jnmgCBJtTNy1vdf2S8qIPvctnI5P/AI9x9KAFDauFEbw6OATlFGSCaALt0kraUEna1trlCM7dpTbnn7wPagDPgF3LaPBLc6aJvMVUeILlmBJbORjO3PQetAEvmayd5R9JKqQhbB5OOVP6UAV7i31SKRJ5otE3AAAumNuSBgfWgC5J/aHkweRHpSzrnzC3TPGCuOnf9KAKzjWkvFDPpKLIOIyPvjGc+v60ASTW2o3NrGy/2Xcq0ASbzVypfnpgdMYH+eQBBDqufLjtNGKDhAV5x24oAfcR3cmoPCf7MAgizFGQCwJ65B6Dr0oAZanU/sb4/sl5siPI+6ygHOcd844oAfC98jn7UdKNsj/vMDGzjp9cH9aAE+zajDHLLHbaazyzDaNo2AY5JPXPAoAjlbxFMDGsOll5cjcvO3AOCcnnkCgBvlX88gj1GHSJY4MM4IyY1zx9AMHH0oAk8mQNFNbTWBySGRo0Chs8AYGeme9AE+nnUJL2OWeLTNpY72i5fOGyQfXOP1oA3qAFoAaRzSAdTAKACgDnvECQm6iL6RJeyMuFZTgDGTg0AVLgfaLv7Tc+G5nkBG1lcdhx3oAkjhGszkanokkbMudxfj5Rx/OgCGxxbW7BfDlwhJ+YK4OQDkdfrQA0xwaxqVxcXOg3DFEyC7Y+YcYH4GgCAWFu0kIbwxKoLguWk6ZXtz64FIDRezCQXdnFoebZMyKC/wDrXyMY5pgNe0/tCKGa40IrLGVjAkfICgEg4B6ZwPxoAqw2UUh8x/C8iyEAsfM4ycZxzQBLdQvdRWs03h8y+XABsD/MrZxgc9O9ADrdSlk1q3hyRI924gOACcH/AD+NAEl7o1vYxwXGnaX5knJwXIZMKSO/XIA/GgCIxxahqFzd3nh+VCkauJGfl9oPGB+VAECWlpsWSPwxMfM6fOMAe4/AUgLK20clhcQDw/IsZKyeWzjLseD+QpgMcb4EtP8AhHJ/s67jgyDrj60ATi0h0q7Wa10GZ3UDa6SA/eHPU9uaAGzq1mbiO20GSWO5RGkO7qTkkHntmgCtcWiSMlx/wj0jee5MwaT5hjPPXvQBY0uytV1GCQaFNbOG+V2kyF4Y5x/n7woA6mgAoAaetIB1MAoAKAM+/wBJS+nSf7RNDIg2gxNjI9KAKj+HZC2U1jUE9vNB/mKAJJtB8+1it5b64YRqylyw3Nk+v6UAQ2/haCC2kg+23TrIpUlpOecd/wAKALelaQNKVo47qaWNjnEhyfzoAgi8PeVdrcDUr0kbdymXIfDEjPHuRSAVvD++fzW1O+xuJ2CXA6njp70wG/8ACODduGp3wbnnzeeg9vagCaLQ0ha3KXlyFgiWLbv4cLu5PHX5v0FAFSLwosESxxarfoq9AJR/hQBYh0ARrtk1C7nw4YeawPQEdMe/8qAIP+EYPmGT+17/AHNkMfMHI446e1ACr4YKQpGmq3y7F2giQZxn6UATz6JJNHAn9qXqeSm3KOAX5zk8daAIR4ZVdmzUrxNo+bDj5/mZuePVz+lAEz6FuijT+0LwNGxPmCT5jkDgnHTigCJvDsjEH+2dQGAOkg/PpQBZk0jzcB7y4ZRGqbSwwSDnceOSaAKs3hoTgh9Tvcb9wAcYX2AxQBPY6I1ldrcHUbucqhQLKwIwSCe3sKANWgBKAGk80gHUwFoAKAKd3eT28oSKylnG3O5CMD2oAhXUrptoGl3AJ65wMUAINVuigb+yrnO4gjjgbc5/p9aAFfUrlLsw/wBmTsmceauNtADV1S6Zox/ZNyAzAMTj5M9+vP4UASre3bzFRp0gT5vnZlHTpx70gCK8v2GZNOZOD/y0B+lMAe7vwBs04scZP71QM+lAFqCSSRW82IxsDjGc5460AS0AFABQAlAC0AJQAUAFABQAtAEUsjpLEqxF1diGYfwDBOfzGPxoAloASgBp60gH0wCgAoASgAoAKACgAoAKAFoASgBaACgAoAKACgAoAKACgBKAFoAKAEoAWgBKAGHrSAkpgFABQAUAFABQAUAFABQAUAFABQAUAFABQAlAC0AFABQAUAFABQAlAC0AIaAIiwzRZiP/2Q== + recorded_at: Tue, 20 Feb 2024 15:37:22 GMT +- request: + method: get + uri: https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmGetImageInfo/p245801coll10/355915/json + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Tue, 20 Feb 2024 15:37:22 GMT + Server: + - Apache + X-Content-Type-Options: + - nosniff + - nosniff + X-Xss-Protection: + - 1; mode=block + - 1; mode=block + X-Oclc-Iiif-Provider: + - cantaloupe + Access-Control-Allow-Origin: + - "*" + Vary: + - Accept-Encoding + Content-Length: + - '204' + Content-Type: + - application/json + Cache-Control: + - max-age=0 + Expires: + - Tue, 20 Feb 2024 15:37:22 GMT + body: + encoding: ASCII-8BIT + string: '{"filename":"\/cdm\/sites\/16002\/data\/p245801coll10\/image\/358713.pdfpage","type":"","width":0,"height":0,"title":"Assessing + English Environment Personality and its Role in Oral Proficiency - Page 62"}' + recorded_at: Tue, 20 Feb 2024 15:37:22 GMT +- request: + method: get + uri: https://digital.library.temple.edu/utils/ajaxhelper/?CISOPTR=355915&CISOROOT=p245801coll10&DMHEIGHT=340&DMSCALE=50&action=2 + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Tue, 20 Feb 2024 15:37:23 GMT + Server: + - Apache + X-Content-Type-Options: + - nosniff + X-Xss-Protection: + - 1; mode=block + X-Oclc-Iiif-Provider: + - cantaloupe + Vary: + - X-Forwarded-Proto + Set-Cookie: + - PHPSESSID=8000fd08e79a67793a105131bb5c410a; path=/; HttpOnly + Expires: + - Tue, 05 Mar 2024 15:37:23 GMT + Cache-Control: + - maxage=1209600 + Pragma: + - public + Content-Length: + - '0' + Content-Type: + - image/jpeg + body: + encoding: UTF-8 + string: '' + recorded_at: Tue, 20 Feb 2024 15:37:23 GMT +- request: + method: get + uri: https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmGetImageInfo/p245801coll10/355918/json + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Tue, 20 Feb 2024 15:37:23 GMT + Server: + - Apache + X-Content-Type-Options: + - nosniff + - nosniff + X-Xss-Protection: + - 1; mode=block + - 1; mode=block + X-Oclc-Iiif-Provider: + - cantaloupe + Access-Control-Allow-Origin: + - "*" + Vary: + - Accept-Encoding + Content-Length: + - '204' + Content-Type: + - application/json + Cache-Control: + - max-age=0 + Expires: + - Tue, 20 Feb 2024 15:37:23 GMT + body: + encoding: ASCII-8BIT + string: '{"filename":"\/cdm\/sites\/16002\/data\/p245801coll10\/image\/358716.pdfpage","type":"","width":0,"height":0,"title":"Assessing + English Environment Personality and its Role in Oral Proficiency - Page 65"}' + recorded_at: Tue, 20 Feb 2024 15:37:23 GMT +- request: + method: get + uri: https://digital.library.temple.edu/utils/ajaxhelper/?CISOPTR=355918&CISOROOT=p245801coll10&DMHEIGHT=340&DMSCALE=50&action=2 + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Tue, 20 Feb 2024 15:37:23 GMT + Server: + - Apache + X-Content-Type-Options: + - nosniff + X-Xss-Protection: + - 1; mode=block + X-Oclc-Iiif-Provider: + - cantaloupe + Vary: + - X-Forwarded-Proto + Set-Cookie: + - PHPSESSID=bc62ad5e30b85b7af43f17829a11771b; path=/; HttpOnly + Expires: + - Tue, 05 Mar 2024 15:37:23 GMT + Cache-Control: + - maxage=1209600 + Pragma: + - public + Content-Length: + - '0' + Content-Type: + - image/jpeg + body: + encoding: UTF-8 + string: '' + recorded_at: Tue, 20 Feb 2024 15:37:23 GMT +- request: + method: get + uri: https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmGetImageInfo/p15037coll17/384/json + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Tue, 20 Feb 2024 15:37:23 GMT + Server: + - Apache + X-Content-Type-Options: + - nosniff + - nosniff + X-Xss-Protection: + - 1; mode=block + - 1; mode=block + X-Oclc-Iiif-Provider: + - cantaloupe + Access-Control-Allow-Origin: + - "*" + Vary: + - Accept-Encoding + Content-Length: + - '137' + Content-Type: + - application/json + Cache-Control: + - max-age=0 + Expires: + - Tue, 20 Feb 2024 15:37:23 GMT + body: + encoding: ASCII-8BIT + string: '{"filename":"\/cdm\/sites\/16002\/data\/p15037coll17\/image\/385.jp2","type":"jp2","width":5385,"height":4233,"title":"Baker, + Josephine"}' + recorded_at: Tue, 20 Feb 2024 15:37:24 GMT +- request: + method: get + uri: https://digital.library.temple.edu/utils/ajaxhelper/?CISOPTR=384&CISOROOT=p15037coll17&DMHEIGHT=340&DMSCALE=6&action=2 + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Tue, 20 Feb 2024 15:37:24 GMT + Server: + - Apache + X-Content-Type-Options: + - nosniff + X-Xss-Protection: + - 1; mode=block + X-Oclc-Iiif-Provider: + - cantaloupe + Vary: + - X-Forwarded-Proto + Set-Cookie: + - PHPSESSID=5f43ea9594f32dd9ed2c17a1748d6607; path=/; HttpOnly + Expires: + - Tue, 05 Mar 2024 15:37:24 GMT + Cache-Control: + - maxage=1209600 + Pragma: + - public + Transfer-Encoding: + - chunked + Content-Type: + - image/jpeg + body: + encoding: ASCII-8BIT + string: !binary |- + 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 + recorded_at: Tue, 20 Feb 2024 15:37:24 GMT +- request: + method: get + uri: https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmGetImageInfo/p15037coll17/385/json + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Tue, 20 Feb 2024 15:37:24 GMT + Server: + - Apache + X-Content-Type-Options: + - nosniff + - nosniff + X-Xss-Protection: + - 1; mode=block + - 1; mode=block + X-Oclc-Iiif-Provider: + - cantaloupe + Access-Control-Allow-Origin: + - "*" + Vary: + - Accept-Encoding + Content-Length: + - '137' + Content-Type: + - application/json + Cache-Control: + - max-age=0 + Expires: + - Tue, 20 Feb 2024 15:37:24 GMT + body: + encoding: ASCII-8BIT + string: '{"filename":"\/cdm\/sites\/16002\/data\/p15037coll17\/image\/386.jp2","type":"jp2","width":4166,"height":5576,"title":"Baker, + Josephine"}' + recorded_at: Tue, 20 Feb 2024 15:37:24 GMT +- request: + method: get + uri: https://digital.library.temple.edu/utils/ajaxhelper/?CISOPTR=385&CISOROOT=p15037coll17&DMHEIGHT=340&DMSCALE=6&action=2 + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Tue, 20 Feb 2024 15:37:25 GMT + Server: + - Apache + X-Content-Type-Options: + - nosniff + X-Xss-Protection: + - 1; mode=block + X-Oclc-Iiif-Provider: + - cantaloupe + Vary: + - X-Forwarded-Proto + Set-Cookie: + - PHPSESSID=04cfd66befde0e5c3bb5325bcd6812b9; path=/; HttpOnly + Expires: + - Tue, 05 Mar 2024 15:37:25 GMT + Cache-Control: + - maxage=1209600 + Pragma: + - public + Transfer-Encoding: + - chunked + Content-Type: + - image/jpeg + body: + encoding: ASCII-8BIT + string: !binary |- + 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 + recorded_at: Tue, 20 Feb 2024 15:37:25 GMT +- request: + method: get + uri: https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmGetImageInfo/p15037coll17/386/json + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Tue, 20 Feb 2024 15:37:25 GMT + Server: + - Apache + X-Content-Type-Options: + - nosniff + - nosniff + X-Xss-Protection: + - 1; mode=block + - 1; mode=block + X-Oclc-Iiif-Provider: + - cantaloupe + Access-Control-Allow-Origin: + - "*" + Vary: + - Accept-Encoding + Content-Length: + - '144' + Content-Type: + - application/json + Cache-Control: + - max-age=0 + Expires: + - Tue, 20 Feb 2024 15:37:25 GMT + body: + encoding: ASCII-8BIT + string: '{"filename":"\/cdm\/sites\/16002\/data\/p15037coll17\/image\/387.jp2","type":"jp2","width":4927,"height":3955,"title":"Alexander, + Raymond Pace"}' + recorded_at: Tue, 20 Feb 2024 15:37:25 GMT +- request: + method: get + uri: https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmGetImageInfo/p15037coll17/387/json + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Tue, 20 Feb 2024 15:37:25 GMT + Server: + - Apache + X-Content-Type-Options: + - nosniff + - nosniff + X-Xss-Protection: + - 1; mode=block + - 1; mode=block + X-Oclc-Iiif-Provider: + - cantaloupe + Access-Control-Allow-Origin: + - "*" + Vary: + - Accept-Encoding + Content-Length: + - '163' + Content-Type: + - application/json + Cache-Control: + - max-age=0 + Expires: + - Tue, 20 Feb 2024 15:37:25 GMT + body: + encoding: ASCII-8BIT + string: '{"filename":"\/cdm\/sites\/16002\/data\/p15037coll17\/image\/388.jp2","type":"jp2","width":3222,"height":2562,"title":"Frazier, + Joe, William Sharpe and Ira Davis"}' + recorded_at: Tue, 20 Feb 2024 15:37:25 GMT +- request: + method: get + uri: https://digital.library.temple.edu/digital/bl/dmwebservices/index.php?q=dmGetImageInfo/p15037coll17/389/json + body: + encoding: US-ASCII + string: '' + headers: + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - "*/*" + User-Agent: + - Ruby + response: + status: + code: 200 + message: OK + headers: + Date: + - Tue, 20 Feb 2024 15:37:25 GMT + Server: + - Apache + X-Content-Type-Options: + - nosniff + - nosniff + X-Xss-Protection: + - 1; mode=block + - 1; mode=block + X-Oclc-Iiif-Provider: + - cantaloupe + Access-Control-Allow-Origin: + - "*" + Vary: + - Accept-Encoding + Content-Length: + - '172' + Content-Type: + - application/json + Cache-Control: + - max-age=0 + Expires: + - Tue, 20 Feb 2024 15:37:25 GMT + body: + encoding: ASCII-8BIT + string: '{"filename":"\/cdm\/sites\/16002\/data\/p15037coll17\/image\/390.jp2","type":"jp2","width":5421,"height":4613,"title":"Clayton, + Zack and Charles "Tarzan" Cooper"}' + recorded_at: Tue, 20 Feb 2024 15:37:25 GMT +recorded_with: VCR 6.2.0 diff --git a/spec/search_engines/cdm_seach_spec.rb b/spec/search_engines/cdm_seach_spec.rb deleted file mode 100644 index a9a49ee98..000000000 --- a/spec/search_engines/cdm_seach_spec.rb +++ /dev/null @@ -1,39 +0,0 @@ -# frozen_string_literal: true - -require "rails_helper" - -RSpec.describe "cdm search engine", type: :search_engine do - - let(:query) { "foo" } - let(:search_results) { BentoSearch.get_engine("cdm").search(query) } - let(:content_dm_results) { { "results" => { "pager" => { "total" => "415" } } } } - - before do - stub_request(:get, /contentdm/) - .to_return(status: 200, - headers: { "Content-Type" => "application/json" }, - body: JSON.dump(content_dm_results)) - end - - it "sets the total found items" do - expect(search_results.total_items).to eq("415") - end - - context "non ASCII query" do - let(:query) { "Read Myron H. Dembo. 2004. Motivation and Learning Strategies for College Success: A Self-Management Approach, Chapter 1, “Academic Self-Management,” 3-17." } - - it "handles non asci queries" do - expect(search_results.total_items).to eq("415") - end - end - - context "when an error gets thrown while processing CDM" do - let(:query) { "query/" } - - it "defaults to 0 finds" do - allow(CDM).to receive(:find).with("query%20") { raise StandardError.new("Boo!") } - allow(Honeybadger).to receive(:notify).with("Ran into error while try to process CDM: Boo!") - expect(search_results.total_items).to eq(0) - end - end -end diff --git a/spec/search_engines/cdm_search_spec.rb b/spec/search_engines/cdm_search_spec.rb new file mode 100644 index 000000000..920aba2f1 --- /dev/null +++ b/spec/search_engines/cdm_search_spec.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +require "rails_helper" + +RSpec.describe "cdm search engine", type: :search_engine do + + let(:query) { "ymca" } + let(:cdm_fields) { "title!date" } + let(:cdm_format) { "json" } + let(:search_engine) { BentoSearch.get_engine("cdm") } + let(:search_results) { VCR.use_cassette("bento_search_cdm") { search_engine.search(query, cdm_fields: cdm_fields, cdm_format: cdm_format) } } + let(:expected_fields) { RSpec.configuration.cdm_expected_fields } + + let(:item) { search_results[0] } + + context "cdm engine" do + it "has all the expected fields" do + expected_fields.each do |field| + expect(item.send field).not_to be_nil, "expect #{field.inspect} to be set." + end + end + + it "uses TulStandardDecorator" do + expect(item.decorator).to eq("TulDecorator") + end + end + + context "gets three displayable results" do + it "includes only records with displayable images" do + search_results.each do |result| + stub_request(:get, result.cdm_thumbnail_link).to_return(status: 200) + end + end + + it "returns only results with non-number titles" do + search_results.each do |result| + expect(result.title.to_f).to eq(0) + end + end + + it "returns three valid results" do + expect(search_results.size).to eq(3) + end + end + + context "when an error gets thrown while processing CDM" do + let(:query) { "query/" } + + it "defaults to 0 finds" do + allow(CDM).to receive(:find).with("query%20") { raise StandardError.new("Boo!") } + allow(Honeybadger).to receive(:notify).with("Ran into error while try to process CDM: Boo!") + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index aa6ea0cce..97983b98b 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -407,7 +407,10 @@ default: [ :title, :link ] config.add_setting :guide_expected_fields, - default: [ :title, :abstract, :link ] + default: [ :title, :abstract, :link ] + + config.add_setting :cdm_expected_fields, + default: [ :title, :cdm_collection, :cdm_date, :cdm_id, :cdm_record_link, :cdm_thumbnail_link ] # So we can test logged in users. From 738ea8280d4b70a099139ab8df281084b41fc1c3 Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Wed, 21 Feb 2024 08:50:05 -0500 Subject: [PATCH 17/20] add view all link --- .../search/_digital_collections.html.erb | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/app/views/search/_digital_collections.html.erb b/app/views/search/_digital_collections.html.erb index 957c9d507..b8a7924ff 100644 --- a/app/views/search/_digital_collections.html.erb +++ b/app/views/search/_digital_collections.html.erb @@ -1,25 +1,22 @@ -<%# format_facet = @response.aggregations["format"] %> - -
    +

    <%= t("bento.digital_collections_header") %>

    -
      - <%# format_facet.items.select do |item| -%> - <%# if item.value == "digital_collections" %> - <% @results["cdm"].each do |cdm_record| %> -
    • - <%= link_to cdm_record.cdm_record_link do %> - <%= image_tag cdm_record.cdm_thumbnail_link %> -
      - <%= cdm_record.title %> -
      - <% end %> -

      - <%= "Date: #{cdm_record.cdm_date}" if cdm_record.cdm_date.present? %> -
      <%= cdm_collection_name(cdm_record.cdm_collection) %> -

      -
    • +
        + <% @results["cdm"].each do |cdm_record| %> +
      • + <%= link_to cdm_record.cdm_record_link do %> + <%= image_tag cdm_record.cdm_thumbnail_link %> +
        + <%= cdm_record.title %> +
        <% end %> - <%# end %> - <%# end %> +

        + <%= "Date: #{cdm_record.cdm_date}" if cdm_record.cdm_date.present? %> +
        <%= cdm_collection_name(cdm_record.cdm_collection) %> +

        +
      • + <% end %> +
        + <%= link_to "View all digitized collections results >", "https://digital.library.temple.edu/digital/search/searchterm/#{params[:q]}/order/nosort" %> +
    From c87df22d4505c81070a4fc5337282471107a8a61 Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Wed, 21 Feb 2024 08:59:35 -0500 Subject: [PATCH 18/20] remove commented code --- app/controllers/search_controller.rb | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index efb0835ce..fde489d47 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -41,28 +41,14 @@ def process_results(results) Honeybadger.notify(result.error[:exception]) if result.failed? end - # unless results["books_and_media"].blank? - # items = BentoSearch::Results.new(results["books_and_media"][0...-1]) - # items.engine_id = results["books_and_media"].engine_id - # items.total_items = results["books_and_media"].total_items - # items.display_configuration = results["books_and_media"].display_configuration - - # # Grabbing and setting @response in order to render facets. - # @response = results["books_and_media"].last.custom_data - - - cdm_total_items = view_context.number_with_delimiter(results["cdm"]&.total_items) unless results["books_and_media"].blank? items = BentoSearch::Results.new(results["books_and_media"][0...-1]) items.engine_id = results["books_and_media"].engine_id - items.total_items = results["books_and_media"].total_items items.display_configuration = results["books_and_media"].display_configuration # Grabbing and setting @response in order to render facets. - # Merges cdm records into the @response. @response = results["books_and_media"].last.custom_data - @response.merge_facet(name: "format", value: "digital_collections", hits: cdm_total_items) results.merge( "books_and_media" => items From 99844a4aad94fca1110ae33577379cfb8689af9b Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Tue, 27 Feb 2024 11:26:49 -0500 Subject: [PATCH 19/20] update fields to re-use BentoSearch default fields --- app/models/bento_search/result_item.rb | 282 ------------------ app/search_engines/bento_search/cdm_engine.rb | 14 +- .../search/_digital_collections.html.erb | 12 +- spec/search_engines/cdm_search_spec.rb | 2 +- spec/spec_helper.rb | 2 +- 5 files changed, 15 insertions(+), 297 deletions(-) delete mode 100644 app/models/bento_search/result_item.rb diff --git a/app/models/bento_search/result_item.rb b/app/models/bento_search/result_item.rb deleted file mode 100644 index 4cc1184d7..000000000 --- a/app/models/bento_search/result_item.rb +++ /dev/null @@ -1,282 +0,0 @@ -# frozen_string_literal: true - -require "language_list" -require "bento_search/author" -require "bento_search/link" - - -module BentoSearch - # Data object representing a single hit from a search, normalized - # with common data fields. Usually held in a BentoSearch::Results object. - # - # ANY field can be nil, clients should be aware. - # - # Each item has a field for one main link as string url, at #link (which may be nil), - # as well as array of possibly additional links (with labels and metadata) - # under #other_links. #other_links is an array of BentoSearch::Link - # objects. - class ResultItem - include ERB::Util # for html_escape for our presentational stuff - include ActionView::Helpers::OutputSafetyHelper # for safe_join - - include ::BentoSearch::Results::Serialization - - # Can initialize with a hash of key/values - def initialize(args = {}) - args.each_pair do |key, value| - send("#{key}=", value) - end - - self.authors ||= [] - self.other_links ||= [] - self.snippets ||= [] - - self.custom_data ||= {} - end - - # internal unique id for the document, from the particular - # search service it came from. May be alphanumeric. May be nil - # for engines that don't support it. - serializable_attr_accessor :unique_id - - - # If set to true, item will refuse to generate an openurl, - # returning nil from #to_openurl or #openurl_kev - serializable_attr_accessor :openurl_disabled - - - # Array (possibly empty) of BentoSearch::Link objects - # representing additional links. Often SearchEngine's themselves - # won't include any of these, but Decorators will be used - # to add them in. - attr_accessor :other_links - serializable_attr :other_links, collection_of: "BentoSearch::Link" - - # * dc.title - # * schema.org CreativeWork: 'name' - serializable_attr_accessor :title - # backwards compat, we used to have separate titles and subtitles - alias_method :complete_title, :title - - # usually a direct link to the search provider's 'native' page. - # Can be changed in actual presentation with a Decorator. - # * schema.org CreativeWork: 'url' - attr_accessor :link - serializable_attr :link - - # does the #link correspond to fulltext? true or false -- or nil - # for unknown/non-applicable. Not all engines will set. - def link_is_fulltext? - @link_is_fulltext - end - def link_is_fulltext=(v) - @link_is_fulltext = v - end - serializable_attr :link_is_fulltext - - # Our own INTERNAL controlled vocab for 'format'. - # - # Important that this be supplied by engine for maximum - # success of openurl, ris export, etc. - # - # This vocab is based on schema.org CreativeWork 'types', - # but supplemented with values we needed not present in schema.org. - # String values are last part of schema.org URLs, symbol values are custom. - # - # However, for backwards compat, values that didn't exist in schema.org - # when we started but later came to exist -- we still use our string - # values. If you actually want a schema.org url, see #schema_org_type_url - # which translates as needed. - # - # schema.org 'type' that's a sub-type of CreativeWork. - # should hold a string that, when appended to "http://schema.org/" - # is a valid schema.org type uri, that sub-types CreativeWork. Ones - # we have used: - # * Article - # * Book - # * Movie - # * MusicRecording - # * Photograph - # * SoftwareApplication - # * WebPage - # * VideoObject - # * AudioObject - # - # - # - # OR one of these symbols, sadly not covered by schema.org types: - # * :serial (magazine or journal) - # * :dissertation (dissertation or thesis) - # * :conference_paper # individual paper - # * :conference_proceedings # collected proceedings - # * :report # white paper or other report. - # * :book_item # section or exceprt from book. - # - # Note: We're re-thinking this, might allow uncontrolled - # in here instead. - serializable_attr_accessor :format - - # Translated from internal format vocab at #format. Outputs - # eg http://schema.org/Book - # Uses the @@format_to_schema_org hash for mapping from - # certain internal symbol values to schema org value, where - # possible. - # - # Can return nil if we don't know a schema.org type - def schema_org_type_url - if format.kind_of? String - "http://schema.org/#{format}" - elsif mapped = @@format_to_schema_org[format] - "http://schema.org/#{mapped}" - else - nil - end - end - @@format_to_schema_org = { - report: "Article", - } - - # uncontrolled presumably english-language format string. - # if supplied will be used in display in place of controlled - # format. - serializable_attr_accessor :format_str - - # Language of materials. Producer can set language_code to an ISO 639-1 (two - # letter) or 639-3 (three letter) language code. If you do this, you don't - # need to set language_str, it'll be automatically looked up. (Providing - # language name in English at present, i18n later maybe). - # - # Or, if you don't know the language code (or there isn't one?), you can set - # language_str manually to a presumably english user-displayable string. - # Manually set language_str will over-ride display string calculated from - # language_code. - # - # Consumers that want a language code can use #language_iso_639_1 or - # #language_iso_639_2 (either may be null), or #language_str for uncontrolled - # string. If engine just sets one of these, internals take care of filling - # out the others. r - serializable_attr_accessor :language_code - attr_writer :language_str - def language_str - (@language_str ||= nil) || language_code.try do |code| - LanguageList::LanguageInfo.find(code.dup).try do |lang_obj| - lang_obj.name - end - end - end - serializable_attr :language_str - # Returns a LanguageList gem language object-- from #language_code - # if available, otherwise from direct language_str if available and - # possible. - def language_obj - @language_obj ||= begin - lookup = self.language_code || self.language_str - LanguageList::LanguageInfo.find(lookup.dup) if lookup - end - end - - # Two letter ISO language code, or nil - def language_iso_639_1 - language_obj.try { |l| l.iso_639_1 } - end - - # Three letter ISO language code, or nil - def language_iso_639_3 - language_obj.try { |l| l.iso_639_3 } - end - - # year published. a ruby int - # PART of:. - # * schema.org CreativeWork "datePublished", year portion - # * dcterms.issued, year portion - # * prism:coverDate, year portion - # - # See also publication_date when you have a complete date - serializable_attr_accessor :year - # ruby stdlib Date object. - attr_accessor :publication_date - serializable_attr :publication_date, serializer: "Date" - - serializable_attr_accessor :volume - serializable_attr_accessor :issue - serializable_attr_accessor :start_page - serializable_attr_accessor :end_page - - # source_title is often used for journal_title (and aliased - # as #journal_title, although that may go away), but can - # also be used for other 'container' titles. Book title for - # a book chapter. Even web site or URL for a web page. - serializable_attr_accessor :source_title - alias_method :journal_title, :source_title - alias_method :'journal_title=', :'source_title=' - - - serializable_attr_accessor :issn - serializable_attr_accessor :isbn - serializable_attr_accessor :oclcnum # OCLC accession number, WorldCat. - - serializable_attr_accessor :doi - serializable_attr_accessor :pmid - - # usually used for books rather than articles - serializable_attr_accessor :publisher - - # an openurl kev-encoded context object. optional, - # only if source provides one that may be better - # than can be constructed from individual elements above - serializable_attr_accessor :openurl_kev_co - - # Short summary of item. - # Mark .html_safe if it includes html -- creator is responsible - # for making sure html is safely sanitizied and/or stripped, - # rails ActionView::Helpers::SanitizeHelper #sanitize and #strip_tags - # may be helpful. - serializable_attr_accessor :abstract - - # An ARRAY of string query-in-context snippets. Will usually - # have highlighting tags in it. Creator is responsible - # for making sure it's otherwise html-safe. - # - # Not all engines may stores Snippets array in addition to abstract, - # some may only store one or the other. Some may store both but - # with same content formatted differently (array of multiple vs - # one combined string), some engines they may be different. - attr_accessor :snippets - serializable_attr :snippets - - # An array (order matters) of BentoSearch::Author objects - # add authors to it with results.authors << Author - attr_accessor :authors - serializable_attr :authors, collection_of: "BentoSearch::Author" - - # engine-specific data not suitable for abstract API, usually - # for internal use. - serializable_attr_accessor :custom_data - - # ContentDM api results attributes - attr_accessor :cdm_date - attr_accessor :cdm_collection - attr_accessor :cdm_id - attr_accessor :cdm_record_link - attr_accessor :cdm_thumbnail_link - - # Copied over from engine configuration usually, a string - # qualified name of a decorator class. Can be nil for default. - attr_accessor :decorator - - # Copied over from engine configuration :for_display key - # by BentoSearch#search wrapper, here as a convenience t - # parameterize logic in decorators or other presentational logic, based - # on configuration, in places where logic has access to an item but - # not the overall Results obj anymore. - # - # TODO: Consider, should we just copy over the whole Results - # into a backpointing reference instead? And user cover-methods - # for it? Nice thing about the configuration has instead is it's - # easily serializable, it's just data. - # - # Although we intentionally do NOT include these in JSON serialization, ha. - attr_accessor :display_configuration - attr_accessor :engine_id - end -end diff --git a/app/search_engines/bento_search/cdm_engine.rb b/app/search_engines/bento_search/cdm_engine.rb index 111b1827b..0f528b0fa 100644 --- a/app/search_engines/bento_search/cdm_engine.rb +++ b/app/search_engines/bento_search/cdm_engine.rb @@ -11,11 +11,11 @@ def conform_to_bento_result(item) cdm_id = item.fetch("pointer") BentoSearch::ResultItem.new( title: item.fetch("title"), - cdm_date: item.fetch("date"), - cdm_collection: cdm_collection, - cdm_id: cdm_id, - cdm_record_link: "https://digital.library.temple.edu/digital/collection/#{cdm_collection}/id/#{cdm_id}", - cdm_thumbnail_link: image_scale(cdm_collection, cdm_id) + publication_date: item.fetch("date"), + source_title: cdm_collection, + unique_id: cdm_id, + link: "https://digital.library.temple.edu/digital/collection/#{cdm_collection}/id/#{cdm_id}", + other_links: [image_scale(cdm_collection, cdm_id)] ) end @@ -43,10 +43,10 @@ def search_implementation(args) response = JSON.load(URI.open(cdm_url)) bento_results.total_items = response.dig("pager", "total") || 0 - response["records"].each do |i| + response["records"].each do |i| item = BentoSearch::ResultItem.new item = conform_to_bento_result(i) - if (bento_results.size < 3) && (image_available?(item.cdm_thumbnail_link)) + if (bento_results.size < 3) && (image_available?(item.other_links[0])) # only take records with images and with alphanumeric titles bento_results << item unless is_int?(item.title) end end diff --git a/app/views/search/_digital_collections.html.erb b/app/views/search/_digital_collections.html.erb index b8a7924ff..2ef5e29d5 100644 --- a/app/views/search/_digital_collections.html.erb +++ b/app/views/search/_digital_collections.html.erb @@ -3,20 +3,20 @@
      <% @results["cdm"].each do |cdm_record| %>
    • - <%= link_to cdm_record.cdm_record_link do %> - <%= image_tag cdm_record.cdm_thumbnail_link %> + <%= link_to cdm_record.link do %> + <%= image_tag cdm_record.other_links[0] %>
      <%= cdm_record.title %>
      <% end %>

      - <%= "Date: #{cdm_record.cdm_date}" if cdm_record.cdm_date.present? %> -
      <%= cdm_collection_name(cdm_record.cdm_collection) %> + <%= "Date: #{cdm_record.publication_date}" if cdm_record.publication_date.present? %> +
      <%= cdm_collection_name(cdm_record.source_title) %>

    • <% end %> -
      +
    +
    <%= link_to "View all digitized collections results >", "https://digital.library.temple.edu/digital/search/searchterm/#{params[:q]}/order/nosort" %>
    -
    diff --git a/spec/search_engines/cdm_search_spec.rb b/spec/search_engines/cdm_search_spec.rb index 920aba2f1..f61e3131b 100644 --- a/spec/search_engines/cdm_search_spec.rb +++ b/spec/search_engines/cdm_search_spec.rb @@ -28,7 +28,7 @@ context "gets three displayable results" do it "includes only records with displayable images" do search_results.each do |result| - stub_request(:get, result.cdm_thumbnail_link).to_return(status: 200) + stub_request(:get, result.other_links).to_return(status: 200) end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 97983b98b..914a97914 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -410,7 +410,7 @@ default: [ :title, :abstract, :link ] config.add_setting :cdm_expected_fields, - default: [ :title, :cdm_collection, :cdm_date, :cdm_id, :cdm_record_link, :cdm_thumbnail_link ] + default: [ :title, :source_title, :publication_date, :unique_id, :link, :other_links ] # So we can test logged in users. From 6a908343b68608f498221076e4bdee3b00d24536 Mon Sep 17 00:00:00 2001 From: Chris Doyle Date: Tue, 27 Feb 2024 11:38:39 -0500 Subject: [PATCH 20/20] rubocop --- app/search_engines/bento_search/cdm_engine.rb | 2 +- spec/search_engines/cdm_search_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/search_engines/bento_search/cdm_engine.rb b/app/search_engines/bento_search/cdm_engine.rb index 0f528b0fa..68b168669 100644 --- a/app/search_engines/bento_search/cdm_engine.rb +++ b/app/search_engines/bento_search/cdm_engine.rb @@ -43,7 +43,7 @@ def search_implementation(args) response = JSON.load(URI.open(cdm_url)) bento_results.total_items = response.dig("pager", "total") || 0 - response["records"].each do |i| + response["records"].each do |i| item = BentoSearch::ResultItem.new item = conform_to_bento_result(i) if (bento_results.size < 3) && (image_available?(item.other_links[0])) # only take records with images and with alphanumeric titles diff --git a/spec/search_engines/cdm_search_spec.rb b/spec/search_engines/cdm_search_spec.rb index f61e3131b..5fc3050a3 100644 --- a/spec/search_engines/cdm_search_spec.rb +++ b/spec/search_engines/cdm_search_spec.rb @@ -28,7 +28,7 @@ context "gets three displayable results" do it "includes only records with displayable images" do search_results.each do |result| - stub_request(:get, result.other_links).to_return(status: 200) + stub_request(:get, result.other_links[0]).to_return(status: 200) end end