Skip to content

Commit

Permalink
Merge pull request #393 from Minitex/captions-support
Browse files Browse the repository at this point in the history
Provide captions support on A/V items
  • Loading branch information
swandog30 authored Aug 22, 2024
2 parents 6e0f77d + 0234522 commit 30af701
Show file tree
Hide file tree
Showing 45 changed files with 21,586 additions and 1,285 deletions.
1 change: 1 addition & 0 deletions .env.test
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# Not a real endpoint
SLACK_NOTIFY_URL=https://hooks.slack.com/triggers/mdl-unit-test-endpoint
KALTURA_SESSION=
2 changes: 0 additions & 2 deletions .github/workflows/validate-pull-request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ jobs:
run: yarn install
- name: Setup DB
run: bin/rails db:schema:load
- name: Prep UV
run: ./prep_uv.sh
- name: Run Backend Tests
run: bundle exec rspec --tag ~skip_ci
- name: Upload Capybara Saved Pages
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ When you update certain frontend elements of the app, you'll need to rebuild the

5) Remove the images

`docker rm $IMAGE_ID`
`docker rmi $IMAGE_ID`

6) Build the new image (assuming you're done making changes for now)

Expand Down
6 changes: 3 additions & 3 deletions app/assets/javascripts/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,22 @@
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require 'blacklight_advanced_search'

//= require jquery3
//= require rails-ujs
//= require popper
//= require twitter/typeahead
//= require bootstrap
//= require chosen-jquery

// Required by Blacklight
//= require blacklight_advanced_search
//= require blacklight/blacklight

//= require_tree .


// For blacklight_range_limit built-in JS, if you don't want it you don't need
// this:
//= require 'blacklight_range_limit'
//= require blacklight_range_limit

9 changes: 7 additions & 2 deletions app/assets/stylesheets/mdl.scss
Original file line number Diff line number Diff line change
Expand Up @@ -1505,8 +1505,13 @@ a.view-text:hover {
}

.iiif-av-component .controls-container {
position: relative;
z-index: 10;
.volume {
float: left !important;
}

.captions-button {
padding-top: 10px;
}
}
/* End item page styles */

Expand Down
23 changes: 14 additions & 9 deletions app/controllers/catalog_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ class CatalogController < ApplicationController
before_action :permit_search_parameters, only: [:index, :range_limit, :oai]
before_action :manage_pagination, only: :index

rescue_from(Blacklight::Exceptions::RecordNotFound, with: :invalid_document_id_error)

##
# Determine whether to render the bookmarks control
def render_bookmarks_control?
Expand Down Expand Up @@ -191,15 +193,6 @@ def parse_referrer_pagination_params(query_string)
## Model that maps search index responses to the blacklight response model
# config.response_model = Blacklight::Solr::Response

## Default parameters to send to solr for all search-like requests. See also SearchBuilder#processed_parameters
config.default_solr_params = {
rows: 20,
fl: '*',
hl: 'on',
'hl.fl': '*',
'hl.fragsize': 0
}

config.default_per_page = 25

config.autocomplete_enabled = false
Expand Down Expand Up @@ -383,6 +376,18 @@ def parse_referrer_pagination_params(query_string)
config.add_index_field 'type_tesi', label: 'Type', highlight: true
config.add_index_field 'physical_format_tesi', label: 'Format', highlight: true

field_list = 'id,title_tesi,timestamp,identifier_ssim,' +
SolrDocument::OAI_FIELDS.join(',') +
',' +
config.index_fields.keys.join(',')
# Default parameters to send to solr for all search-like requests.
config.default_solr_params = {
rows: 20,
fl: field_list,
hl: 'on',
'hl.fl': field_list,
'hl.fragsize': 0
}

# solr fields to be displayed in the show (single result) view
# The ordering of the field names is the order of the display
Expand Down
39 changes: 37 additions & 2 deletions app/controllers/iiif_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,50 @@ class IiifController < ApplicationController
render json: { status: :internal_server_error }, status: :internal_server_error
end

FIELD_LIST = MDL::CiteDetails
.field_configs
.map(&:key)
.to_set
.merge(Set[
'id',
'title_ssi',
'rights_uri_ssi',
'contact_information_ssi',
'iiif_manifest_ss',
'format_tesi',
'kaltura_audio_playlist_entry_data_ts',
'dimensions_ssi',
'kaltura_audio_playlist_ssi',
'kaltura_audio_ssi',
'rights_statement_ssi',
'kaltura_video_playlist_ssi',
'kaltura_audio_playlist_ssi',
'kaltura_video_playlist_entry_data_ts',
'kaltura_video_ssi'
])
.join(',')
.freeze
private_constant :FIELD_LIST

include Blacklight::Catalog

configure_blacklight do |config|
config.default_document_solr_params = {
qt: 'document',
fl: FIELD_LIST,
rows: 1
}
end

def manifest
_response, document = search_service.fetch(params[:id])
if document.key?('iiif_manifest_ss')
render body: document['iiif_manifest_ss'], content_type: 'application/json'
else
doc = MDL::BorealisDocument.new(document: document)
manifest = IiifManifest.new(doc)
base_uri = URI::HTTPS.build(host: request.host)
doc = MDL::BorealisDocument.new(document:)
manifest = IiifManifest.new(doc, base_url: base_uri.to_s)
headers['access-control-allow-origin'] = '*'
render json: manifest
end
end
Expand Down
41 changes: 41 additions & 0 deletions app/controllers/tracks_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
class TracksController < ApplicationController
before_action :set_cors_headers

def entry
respond_to do |format|
format.vtt do
content = fetch_vtt_content
head :not_found and return unless content.present?

vtt_content = JSON.parse(content).dig(params[:entry_id])
head :not_found and return unless vtt_content.present?

render plain: "WEBVTT\n\n#{vtt_content}", content_type: 'text/vtt'
end
end
end

private

# TODO: remove
def set_cors_headers
headers['access-control-allow-origin'] = '*'
headers['access-control-allow-methods'] = 'GET'
headers['access-control-allow-headers'] = 'Accept, Accept-Language, Content-Type, Authorization'
end

def fetch_vtt_content
client = Blacklight.default_index.connection
response = client.get('select', params: {
defType: 'edismax',
fq: "id:\"#{RSolr.solr_escape(params[:id])}\"",
fl: 'captions_ts',
qt: 'search',
rows: 1,
q: '*:*',
wt: 'json'
})
docs = Array(response.dig('response', 'docs'))
docs.first&.[]('captions_ts')
end
end
18 changes: 0 additions & 18 deletions app/controllers/uvconfig_controller.rb

This file was deleted.

3 changes: 0 additions & 3 deletions app/javascript/packs/universalviewer.js

This file was deleted.

1 change: 0 additions & 1 deletion app/javascript/packs/universalviewer_lib.js

This file was deleted.

80 changes: 63 additions & 17 deletions app/models/iiif_manifest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,34 @@ class IiifManifest
format: 'image/jpeg'
}
}.freeze
private_constant :ANNOTATION_DATA_BY_TYPE
RENDERABLE_ASSET_CLASSES = ANNOTATION_DATA_BY_TYPE.keys.freeze
private_constant :RENDERABLE_ASSET_CLASSES
AV_ASSETS = [MDL::BorealisVideo, MDL::BorealisAudio].freeze
private_constant :AV_ASSETS

delegate :collection,
:id,
:title,
:assets,
to: :borealis_document

# @return [MDL::BorealisDocument]
attr_reader :borealis_document

def initialize(borealis_document)
# @return [String]
attr_reader :base_url

###
# @param borealis_document [MDL::BorealisDocument]
# @param base_url [String]
def initialize(borealis_document, base_url:)
@borealis_document = borealis_document
@base_url = base_url
end

###
# @return [Hash]
def as_json(*)
{
'@context' => 'http://iiif.io/api/presentation/3/context.json',
Expand All @@ -58,7 +73,7 @@ def as_json(*)
}
}
end,
'items' => canvasable_assets.map { |a| canvas(a) }
'items' => canvasable_assets.map(&method(:canvas))
}.tap do |hsh|
if borealis_document.document['rights_statement_ssi']
hsh['requiredStatement'] = {
Expand All @@ -67,7 +82,7 @@ def as_json(*)
}
end
if renderable_assets.any?
hsh['rendering'] = renderable_assets.map { |a| rendering(a) }.flatten
hsh['rendering'] = renderable_assets.flat_map(&method(:rendering))
end
if rangeable_assets.any?
hsh['structures'] = rangeable_assets
Expand All @@ -80,13 +95,13 @@ def as_json(*)
private

def details
MDL::CiteDetails.new(
solr_doc: borealis_document.document
).details
MDL::CiteDetails
.new(solr_doc: borealis_document.document)
.details
end

def base_identifier
"https://collection.mndigital.org/iiif/info/#{collection}/#{id}"
"#{base_url}/iiif/info/#{collection}/#{id}"
end

def canvas(asset)
Expand Down Expand Up @@ -115,6 +130,22 @@ def canvas(asset)
hsh['duration'] = asset.playlist_data.sum { |d| d['duration'] }
else
hsh['duration'] = borealis_document.duration
if !asset.playlist?
hsh['rendering'] = [
{
'id' => vtt_url(asset.entry_id),
'type' => 'Text',
'label' => { 'en' => ['English'] },
'format' => 'text/vtt'
},
{
'id' => asset.src,
'type' => annotation_body_type(asset),
'duration' => borealis_document.duration,
'format' => annotation_body_format(asset)
}
]
end
end
width, height = annotation_aspect(asset)

Expand All @@ -128,6 +159,12 @@ def canvas(asset)
end
end

# @param entry_id [String]
# @return [String]
def vtt_url(entry_id)
"#{base_url}/tracks/#{collection}:#{id}/entry/#{entry_id}.vtt"
end

def annotation_items(asset, canvas_id)
if asset.playlist?
playlist_annotation_items(asset, canvas_id)
Expand Down Expand Up @@ -175,7 +212,21 @@ def playlist_annotation_items(asset, canvas_id)
hsh['width'] = width if width
hsh['height'] = height if height
end,
'target' => target
'target' => target,
'rendering' => [
{
'id' => vtt_url(data['entry_id']),
'type' => 'Text',
'label' => { 'en' => ['English'] },
'format' => 'text/vtt'
},
{
'id' => asset.src(data['entry_id']),
'type' => type,
'duration' => data['duration'],
'format' => body_format
}
]
}
end
end
Expand All @@ -193,7 +244,7 @@ def rendering(asset)
}
end
else
{
[{
'id' => asset.src,
'type' => annotation_body_type(asset),
'label' => {
Expand All @@ -207,7 +258,7 @@ def rendering(asset)
'format' => 'image/jpeg'
}
]
}
}]
end
end

Expand Down Expand Up @@ -248,18 +299,13 @@ def canvas_id(asset)

def canvasable_assets
assets.select do |a|
[MDL::BorealisVideo, MDL::BorealisAudio].include?(a.class)
AV_ASSETS.include?(a.class)
end
end

def renderable_assets
assets.select do |a|
[
MDL::BorealisVideo,
MDL::BorealisAudio,
MDL::BorealisPdf,
MDL::BorealisImage
].include?(a.class)
RENDERABLE_ASSET_CLASSES.include?(a.class)
end
end

Expand Down
Loading

0 comments on commit 30af701

Please sign in to comment.