From 6ca48cbcc8cf73d070426adb657c025107423e97 Mon Sep 17 00:00:00 2001 From: cjcolvar Date: Thu, 20 Mar 2025 23:36:21 -0400 Subject: [PATCH] Searches can return IIIF Collection manifests --- Gemfile | 3 +- Gemfile.lock | 12 +++- app/controllers/catalog_controller.rb | 12 ++++ .../iiif_collection_manifest_presenter.rb | 70 +++++++++++++++++++ .../speedy_af/proxy/media_object.rb | 2 +- config/routes.rb | 2 + 6 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 app/models/iiif_collection_manifest_presenter.rb diff --git a/Gemfile b/Gemfile index 85619cb909..0b0e8d396b 100644 --- a/Gemfile +++ b/Gemfile @@ -58,7 +58,8 @@ gem 'avalon-about', git: 'https://github.com/avalonmediasystem/avalon-about.git' #gem 'bootstrap-sass', '< 3.4.1' # Pin to less than 3.4.1 due to change in behavior with popovers gem 'bootstrap-toggle-rails' gem 'bootstrap_form' -gem 'iiif_manifest', '~> 1.6' +gem 'iiif_manifest', git: 'https://github.com/samvera/iiif_manifest.git', branch: 'v3_collections' +#gem 'iiif_manifest', '~> 1.6' gem 'rack-cors', require: 'rack/cors' gem 'rails_same_site_cookie' gem 'recaptcha', require: 'recaptcha/rails' diff --git a/Gemfile.lock b/Gemfile.lock index 7fbec3dc58..047cf57ff6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -77,6 +77,14 @@ GIT rsolr (>= 1.1.2, < 3) ruby-progressbar (~> 1.0) +GIT + remote: https://github.com/samvera/iiif_manifest.git + revision: a3c1c504e9ac36eedb23f39e908ab86593e670a4 + branch: v3_collections + specs: + iiif_manifest (1.6.0) + activesupport (>= 4) + GEM remote: https://rubygems.org/ specs: @@ -462,8 +470,6 @@ GEM i18n (1.14.7) concurrent-ruby (~> 1.0) iconv (1.0.8) - iiif_manifest (1.6.0) - activesupport (>= 4) ims-lti (1.1.13) builder oauth (>= 0.4.5, < 0.6) @@ -1044,7 +1050,7 @@ DEPENDENCIES httpx hydra-head (~> 13.0) iconv (~> 1.0.6) - iiif_manifest (~> 1.6) + iiif_manifest! ims-lti (~> 1.1.13) jbuilder (~> 2.0) jquery-datatables diff --git a/app/controllers/catalog_controller.rb b/app/controllers/catalog_controller.rb index f6a90cafdb..4e8e27e331 100644 --- a/app/controllers/catalog_controller.rb +++ b/app/controllers/catalog_controller.rb @@ -222,6 +222,18 @@ class CatalogController < ApplicationController config.bootstrap_version = 4 end + def manifest + @response = search_service.search_results + + presenter = IiifCollectionManifestPresenter.new(items: @response.documents.map { |doc| SpeedyAF::Base.for(doc) }, params: params) + manifest = IIIFManifest::V3::ManifestFactory.new(presenter).to_h + + respond_to do |wants| + wants.json { render json: manifest.to_json } + wants.html { render json: manifest.to_json } + end + end + private def load_home_page_collections diff --git a/app/models/iiif_collection_manifest_presenter.rb b/app/models/iiif_collection_manifest_presenter.rb new file mode 100644 index 0000000000..58bc0a89a1 --- /dev/null +++ b/app/models/iiif_collection_manifest_presenter.rb @@ -0,0 +1,70 @@ +# Copyright 2011-2024, The Trustees of Indiana University and Northwestern +# University. Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed +# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +# CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# --- END LICENSE_HEADER BLOCK --- + +class IiifCollectionManifestPresenter + attr_reader :items, :params + + def initialize(items:, params:) + @items = items.map { |item| IiifManifestPresenter.new(media_object: item, master_files: nil, lending_enabled: lending_enabled?(item)) } + @params = params + end + + def file_set_presenters + [] + end + + def work_presenters + items + end + + def manifest_url + Rails.application.routes.url_helpers.manifest_catalog_url(nil, *params.except(:action, :controller).permit!) + end + + def to_s + 'Catalog Search' + end + + def collection? + true + end + + def homepage + [ + { + id: Rails.application.routes.url_helpers.search_catalog_url(nil, *params.except(:action, :controller).permit!), + type: "Text", + label: { "none" => [I18n.t('iiif.manifest.homepageLabel')] }, + format: "text/html" + } + ] + end + + def manifest_metadata + @manifest_metadata ||= iiif_metadata_fields.compact + end + + private + + def iiif_metadata_fields + [ + "Title" => to_s + ] + end + + def lending_enabled?(context) + return context&.cdl_enabled? if Avalon::Configuration.controlled_digital_lending_enabled? + false + end +end diff --git a/app/presenters/speedy_af/proxy/media_object.rb b/app/presenters/speedy_af/proxy/media_object.rb index 5eac91744a..1f977cd8e0 100644 --- a/app/presenters/speedy_af/proxy/media_object.rb +++ b/app/presenters/speedy_af/proxy/media_object.rb @@ -25,7 +25,7 @@ def initialize(solr_document, instance_defaults = {}) instance_defaults ||= {} @model = SpeedyAF::Base.model_for(solr_document) @attrs = self.class.defaults.merge(instance_defaults) - solr_document.each_pair do |k, v| + solr_document.to_h.each_pair do |k, v| attr_name, value = parse_solr_field(k, v) @attrs[attr_name.to_sym] = value end diff --git a/config/routes.rb b/config/routes.rb index 82e1e8c3fa..b010c9804b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,6 +8,8 @@ resource :catalog, only: [], as: 'catalog', path: '/catalog', controller: 'catalog' do concerns :searchable + + get :manifest end # For some reason this needs to be after `resource :catalog` otherwise Blacklight will generate links to / instead of /catalog