Skip to content
27 changes: 27 additions & 0 deletions app/assets/javascripts/materials.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
function make_zenodo_video(video_element, files_url, preferred_key) {
const videoExtensions = ['.mp4', '.webm', '.ogg', '.ogv', '.mov', '.m4v', '.mkv'];
const audioExtensions = ['.mp3', '.ogg', '.wav', '.aac', '.flac', '.opus'];
video_element.parentElement.style.display = 'none';

fetch(files_url)
.then(response => response.json())
.then(data => {
let video_file = null;
if (preferred_key != null) {
video_file = data.entries.find(file => file.key === String(preferred_key));
}
if (!video_file) {
video_file = data.entries.find(file => videoExtensions.some(ext => file.key.toLowerCase().endsWith(ext)));
}
if (!video_file) { // fallback to audio
video_file = data.entries.find(file => audioExtensions.some(ext => file.key.toLowerCase().endsWith(ext)));
}
if (video_file) {
const video_url = video_file.links.content;
video_element.src = video_url;
video_element.style.display = 'block';
video_element.parentElement.style.display = 'block';
}
})
.catch(error => console.error('Error fetching Zenodo files:', error));
}
3 changes: 2 additions & 1 deletion app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -886,10 +886,11 @@ input[type=checkbox].field-lock + label:before,

.embedded-content {
margin: 2em auto;
display: flex;
justify-content: center;

iframe {
display: block;
margin: auto;
}
}

Expand Down
10 changes: 9 additions & 1 deletion app/helpers/materials_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,15 @@ def display_attribute_no_label(resource, attribute, markdown: false, &block) # r
end

def embed_youtube(material)
renderer = Renderers::Youtube.new(material)
embed_video(Renderers::Youtube, material)
end

def embed_zenodo(material)
embed_video(Renderers::Zenodo, material)
end

def embed_video(renderer_class, material)
renderer = renderer_class.new(material)
return unless renderer.can_render?

content_tag(:div, class: 'embedded-content') do
Expand Down
1 change: 1 addition & 0 deletions app/views/materials/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
</div>

<%= embed_youtube(@material) %>
<%= embed_zenodo(@material) %>

<!-- Field: long description -->
<div class="description">
Expand Down
33 changes: 33 additions & 0 deletions lib/renderers/zenodo.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module Renderers
class Zenodo
VALID_SCHEMES = %w[http https].freeze
TEMPLATE = %(<video controls height="500" style="display:none;" id="zenodo-video"></video><script>make_zenodo_video(document.getElementById('zenodo-video'), '%<files_url>s', %<key>s);</script>)

def initialize(resource)
@url = resource.url
@parsed_url = begin
Addressable::URI.parse(@url)
rescue StandardError
nil
end
end

def can_render?
@url && @parsed_url && zenodo_id && VALID_SCHEMES.include?(@parsed_url.scheme)
end

def render_content
files_url = "https://zenodo.org/api/records/#{zenodo_id}/files"
key = @parsed_url.query_values.to_h['preview_file']
format(TEMPLATE, files_url:, key: key.to_json).html_safe
end

private

def zenodo_id
match = @parsed_url.host == 'zenodo.org' && @url.match(%r{records/(\d+)}) ||
@parsed_url.host == 'doi.org' && @url.match(%r{10\.5281/zenodo\.(\d+)})
match[1] if match
end
end
end
8 changes: 8 additions & 0 deletions test/controllers/materials_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1353,6 +1353,14 @@ class MaterialsControllerTest < ActionController::TestCase
assert_select 'div.embedded-content iframe[src=?]', 'https://www.youtube.com/embed/1T_2xMTQCv4'
end

test 'can render embedded zenodo video' do
sign_in users(:regular_user)
get :show, params: { id: materials(:zenodo_video_material) }
assert_response :success

assert_select 'div.embedded-content video#zenodo-video'
end

test 'no embedded content section if not available' do
sign_in users(:regular_user)
get :show, params: { id: materials(:good_material) }
Expand Down
14 changes: 14 additions & 0 deletions test/fixtures/materials.yml
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,20 @@ youtube_video_material:
- Video
learning_objectives: In this video, I will show you how to create and run data quality checks in REDCap.

zenodo_video_material:
user: regular_user
title: 'How to Soften Hard Water?'
url: https://zenodo.org/records/17402249
description: In this video, I will show you how to soften hard water.
licence: CC-BY-NC-4.0
contact: contact@elixir-uk.org
keywords:
- water
- "hard water"
resource_type:
- Video
learning_objectives: In this video, I will show you how to soften hard water.

plant_space_material:
user: regular_user
title: Plant material
Expand Down
Loading