Skip to content

Commit

Permalink
Merge pull request #2346 from sul-dlss/2342-media-navbar
Browse files Browse the repository at this point in the history
add content nav bar for media
  • Loading branch information
jcoyne authored Feb 6, 2025
2 parents 4984ad5 + 0a42aa5 commit bd15277
Show file tree
Hide file tree
Showing 10 changed files with 127 additions and 16 deletions.
36 changes: 35 additions & 1 deletion app/assets/stylesheets/media.css
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,9 @@
}

.sul-embed-media-wrapper {
--prev-next-container-height: 65px;
display: inline-block;
height: 100%;
height: calc(100% - var(--prev-next-container-height));
position: relative;
text-align: center;
width: 100%;
Expand All @@ -100,6 +101,39 @@
height: 100%;
width: 100%;
}

.prev-next-container {
height: var(--prev-next-container-height);
display: flex;
flex-direction: column;
justify-content: center; /* Centers content vertically */
align-items: center; /* Centers content horizontally */
.prev-next-buttons {
display: flex;
.left-arrow svg {
transform: rotate(180deg);
}
button {
background: none;
color: inherit;
border: none;
padding: 0;
font: inherit;
cursor: pointer;
width: 1.5rem;
height: 1.5rem;
margin: 0px .25rem;
svg {
fill: #0000008A;
}
&:disabled {
svg {
fill: #0000003D;
}
}
}
}
}
}

/* Second selector is for citation-only banner. First selector is for all the other auth restrictions. */
Expand Down
1 change: 1 addition & 0 deletions app/components/content_list_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<h3><%= heading %></h3>
</div>
<ul class="left-drawer-content"
id="content-list"
data-controller="content-list"
data-action="thumbnails-found@window->content-list#drawThumbnails"
role="tablist">
Expand Down
7 changes: 4 additions & 3 deletions app/components/media/preview_image_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,20 @@ class PreviewImageComponent < ViewComponent::Base
# @param [ResourceFile] file the file to display
# @param [Integer] resource_index the offset of this resource in the purl
# @param [String] type the type of resource (either audio or video), used to determine which icon to show
def initialize(druid:, file:, resource_index:, type:)
def initialize(druid:, file:, resource_index:, type:, size:)
@druid = druid
@file = file
@resource_index = resource_index
@type = type
@size = size
end

attr_reader :resource_index, :druid, :file, :type
attr_reader :resource_index, :druid, :file, :type, :size

def call
# the 74,73 size accounts for the additional pixel size returned by the image server
thumb_url = stacks_square_url(druid, file.title, size: '74,73')
render WrapperComponent.new(thumbnail: thumb_url, file:, type:, resource_index:) do
render WrapperComponent.new(thumbnail: thumb_url, file:, type:, resource_index:, size:) do
tag.div(class: 'osd', id: "openseadragon-#{resource_index}",
data: { controller: 'osd', osd_url_value:, osd_nav_images_value: })
end
Expand Down
4 changes: 3 additions & 1 deletion app/components/media/tag_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ def call
if SUPPORTED_MEDIA_TYPES.include?(type.to_sym)
media_element
else
render PreviewImageComponent.new(druid:, file:, type:, resource_index: @resource_iteration.index)
render PreviewImageComponent.new(druid:, file:, type:, size: @resource_iteration.size,
resource_index: @resource_iteration.index)
end
end

Expand All @@ -50,6 +51,7 @@ def default_audio_thumbnail

def media_element
render WrapperComponent.new(thumbnail: thumbnail_url, file:, type:,
size: @resource_iteration.size,
resource_index: @resource_iteration.index) do
media_tag
end
Expand Down
38 changes: 36 additions & 2 deletions app/components/media/wrapper_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,45 @@

module Media
class WrapperComponent < ViewComponent::Base
def initialize(file:, type:, resource_index:, thumbnail:)
def initialize(file:, type:, resource_index:, thumbnail:, size:)
@file = file
@type = type
@resource_index = resource_index
@thumbnail = thumbnail
@size = size
end

def lr_button(class:, disabled:, index:, label:)
tag.button(arrow, class:, disabled:, aria: { label: },
data: { controller: 'prev-next',
prev_next_content_list_outlet: '#content-list',
action: 'click->prev-next#prevNextMedia',
prev_next_index_param: index })
end

def buttons
lr_button(class: 'left-arrow', disabled: @resource_index.zero?, index: @resource_index - 1,
label: 'Previous item') +
lr_button(class: 'right-arrow', disabled: @resource_index + 1 == @size, index: @resource_index + 1,
label: 'Next item')
end

def prev_next_container
tag.div class: 'prev-next-container' do
tag.div(class: 'prev-next-buttons') do
buttons
end +
tag.div(id: 'current-title') do
tag.span("#{@resource_index + 1} of #{@size}#{@file.label_or_filename}")
end
end
end

def arrow
tag.svg(viewBox: '0 0 24 24') do
tag.path(d: 'm10 16.5 6-4.5-6-4.5zM12 2C6.48 2 2 6.48 2 12s4.48 10
10 10 10-4.48 10-10S17.52 2 12 2m0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8')
end
end

# TODO: stanford_only and location_restricted moved to the media tag,
Expand All @@ -27,7 +61,7 @@ def call # rubocop:disable Metrics/MethodLength
# When rendering this component, show only the first media wrapper component
hidden: !@resource_index.zero?) do
tag.div class: 'sul-embed-media-wrapper' do
content
content + prev_next_container
end
end
end
Expand Down
6 changes: 3 additions & 3 deletions app/javascript/controllers/content_list_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Controller } from "@hotwired/stimulus"
import Thumbnail from 'src/modules/thumbnail'

export default class extends Controller {
static targets = ['listItem']
// This listens for a thumbnails-found event. Then it draws the media thumbnails in the contents panel
drawThumbnails(evt) {
const thumbnails = evt.detail.
Expand All @@ -16,13 +17,12 @@ export default class extends Controller {
const event = new CustomEvent('thumbnail-clicked', { detail: { index: evt.params.index } })
window.dispatchEvent(event)

const tabs = this.element.closest('[role="tablist"]').querySelectorAll('[role="tab"]')
tabs.forEach((target) => {
this.listItemTargets.forEach((target) => {
target.classList.remove('active')
target.setAttribute("aria-selected", false)
})

const target = this.element
const target = this.listItemTargets.find(element => element.dataset.contentListIndexParam == evt.params.index)
target.classList.add('active')
target.setAttribute("aria-selected", true)
}
Expand Down
9 changes: 9 additions & 0 deletions app/javascript/controllers/prev_next_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
static outlets = [ "content-list" ]

prevNextMedia(evt) {
this.contentListOutlet.showMedia(evt);
}
}
2 changes: 1 addition & 1 deletion app/javascript/src/modules/thumbnail.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export default class {
}

// Note: the "position: relative" is required for the stretched-link style.
return `<li class="media-thumb ${activeClass}" data-controller="content-list" data-action="click->content-list#showMedia" data-content-list-index-param="${index}" style="position: relative;" aria-controls="main-display" role="tab">
return `<li class="media-thumb ${activeClass}" data-action="click->content-list#showMedia" data-content-list-target="listItem" data-content-list-index-param="${index}" style="position: relative;" aria-controls="main-display" role="tab">
${thumbnailIcon}
<a class="stretched-link" href="#">
<span class="${labelClass}">
Expand Down
6 changes: 3 additions & 3 deletions spec/components/media/tag_component_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
)
end

let(:resource_iteration) { instance_double(ActionView::PartialIteration, index: 0) }
let(:resource_iteration) { instance_double(ActionView::PartialIteration, index: 0, size: 1) }
let(:druid) { 'bc123df4567' }

before do
Expand All @@ -37,7 +37,7 @@
end

context 'with a stanford only video' do
let(:resource_iteration) { instance_double(ActionView::PartialIteration, index: 1) }
let(:resource_iteration) { instance_double(ActionView::PartialIteration, index: 1, size: 4) }
let(:resource) { build(:resource, :video, files: [build(:resource_file, :video, :stanford_only)]) }

it 'includes a data attribute that includes the url to check the users auth status' do
Expand All @@ -48,7 +48,7 @@
end

context 'with a world access video' do
let(:resource_iteration) { instance_double(ActionView::PartialIteration, index: 3) }
let(:resource_iteration) { instance_double(ActionView::PartialIteration, index: 3, size: 3) }
let(:resource) { build(:resource, :video, files: [build(:resource_file, :video, :world_downloadable)]) }

it 'includes a data attribute that includes the url to check the users auth status' do
Expand Down
34 changes: 32 additions & 2 deletions spec/components/media/wrapper_component_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@
subject(:render) do
render_inline(
described_class.new(
file:, type:, resource_index:, thumbnail:
file:, type:, resource_index:, thumbnail:, size:
)
)
) do
'content'
end
end

let(:resource_index) { 0 }
let(:thumbnail) { '' }
let(:type) { 'audio' }
let(:size) { 10 }

before do
render
Expand All @@ -25,6 +28,9 @@
context 'with audio' do
it 'renders the page' do
expect(page).to have_css('[data-default-icon="sul-i-file-music-1"]')
expect(page).to have_css('button[aria-label="Previous item"][disabled]')
expect(page).to have_css('button[aria-label="Next item"]')
expect(page).to have_no_css('button[aria-label="Next item"][disabled]')
end
end

Expand All @@ -33,6 +39,9 @@

it 'renders the page' do
expect(page).to have_css('[data-default-icon="sul-i-file-video-3"]')
expect(page).to have_css('button[aria-label="Previous item"][disabled]')
expect(page).to have_css('button[aria-label="Next item"]')
expect(page).to have_no_css('button[aria-label="Next item"][disabled]')
end
end
end
Expand All @@ -43,6 +52,9 @@

it 'renders the page' do
expect(page).to have_css('[data-stanford-only="true"]')
expect(page).to have_css('button[aria-label="Previous item"][disabled]')
expect(page).to have_css('button[aria-label="Next item"]')
expect(page).to have_no_css('button[aria-label="Next item"][disabled]')
end
end

Expand All @@ -51,6 +63,9 @@

it 'renders the page' do
expect(page).to have_css('[data-stanford-only="false"]')
expect(page).to have_css('button[aria-label="Previous item"][disabled]')
expect(page).to have_css('button[aria-label="Next item"]')
expect(page).to have_no_css('button[aria-label="Next item"][disabled]')
end
end
end
Expand All @@ -61,6 +76,9 @@

it 'renders the page' do
expect(page).to have_css('[data-location-restricted="true"]')
expect(page).to have_css('button[aria-label="Previous item"][disabled]')
expect(page).to have_css('button[aria-label="Next item"]')
expect(page).to have_no_css('button[aria-label="Next item"][disabled]')
end
end

Expand All @@ -69,6 +87,18 @@

it 'renders the page' do
expect(page).to have_css('[data-location-restricted="false"]')
expect(page).to have_css('button[aria-label="Previous item"][disabled]')
expect(page).to have_css('button[aria-label="Next item"]')
expect(page).to have_no_css('button[aria-label="Next item"][disabled]')
end

context 'when there is only one item' do
let(:size) { 1 }

it 'has both buttons disabled' do
expect(page).to have_css('button[aria-label="Previous item"][disabled]')
expect(page).to have_css('button[aria-label="Next item"][disabled]')
end
end
end
end
Expand Down

0 comments on commit bd15277

Please sign in to comment.