Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🚧 i205 - add ability to upload collection thumbnails #2206

Merged
merged 9 commits into from
May 21, 2024
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,4 @@ docker-compose.override.yml
*~undo-tree~
.DS_Store
/bundler.d/
/uploads
kirkkwang marked this conversation as resolved.
Show resolved Hide resolved
9 changes: 9 additions & 0 deletions app/assets/javascripts/hyrax/fileupload.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//= require hyrax/uploader
// This file is the default initialization of the fileupload. If you want to call
// hyraxUploader with other options (like afterSubmit), then override this file.
Blacklight.onLoad(function() {
var options = {};
$('#fileupload').hyraxUploader(options);
$('#fileuploadlogo').hyraxUploader({downloadTemplateId: 'logo-template-download'});
$('#fileuploadthumbnail').hyraxUploader({downloadTemplateId: 'thumbnail-template-download'});
kirkkwang marked this conversation as resolved.
Show resolved Hide resolved
});
24 changes: 24 additions & 0 deletions app/assets/stylesheets/hyku.scss
Original file line number Diff line number Diff line change
Expand Up @@ -649,3 +649,27 @@ span.constraint-value p, .facet-values p {
tr[data-feature="use-iiif-print"] {
display: none;
}

// collection branding thumbnail
.branding-thumbnail-row {
border-top: solid 1px #dddddd;
padding-top: 10px;
}

.branding-thumbnail-input {
text-align: right;
width: 250px;

input {
text-align: left;
}
}

.branding-thumbnail-remove,
.branding-thumbnail-remove:hover {
background-color: #ffffff;
border-color: #ffffff;
color: $brand-danger;
font-weight: normal;
text-decoration: underline;
}
53 changes: 38 additions & 15 deletions app/controllers/hyrax/dashboard/collections_controller_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
# OVERRIDE Hyrax v5.0.0rc2
# - Fix file upload in logo and banner
# - Use work titles for collection thumbnail select & to add an option to reset to the default thumbnail

# OVERRIDE Hyrax v5.0.0 to add the ability to upload a collection thumbnail

module Hyrax
module Dashboard
## Shows a list of all collections to the admins
Expand All @@ -14,16 +17,36 @@ def show
super
end

private

def configure_show_sort_fields
# In the CollectionsControllerDecorator, we clear the sort fields and add our own to have
# the ability to sort the index with custom fields. However, this also affects the show page.
# Here we set the sort fields back to the defaults for the show page.
blacklight_config.sort_fields = CatalogController.blacklight_config.sort_fields
# OVERRIDE Hyrax v5.0.0 to add the ability to upload a collection thumbnail - START
def process_branding
process_banner_input
process_logo_input
process_thumbnail_input
end

public
# rubocop:disable Metrics/AbcSize
def update_valkyrie_collection
return after_update_errors(form_err_msg(form)) unless form.validate(collection_params)

result = transactions['change_set.update_collection']
.with_step_args(
'collection_resource.save_collection_banner' => { update_banner_file_ids: params["banner_files"],
banner_unchanged_indicator: params["banner_unchanged"] },
'collection_resource.save_collection_logo' => { update_logo_file_ids: params["logo_files"],
alttext_values: params["alttext"],
linkurl_values: params["linkurl"] },
'collection_resource.save_collection_thumbnail' => { update_thumbnail_file_ids: params["thumbnail_files"],
thumbnail_unchanged_indicator: params["thumbnail_unchanged"],
alttext_values: params["thumbnail_text"] }
)
.call(form)
@collection = result.value_or { return after_update_errors(result.failure.first) }

process_member_changes
after_update_response
end
# rubocop:enable Metrics/AbcSize
# OVERRIDE Hyrax v5.0.0 to add the ability to upload a collection thumbnail - END

def edit
form
Expand All @@ -47,13 +70,6 @@ def update
super
end

def process_branding
super

# TODO: does this still work?
process_uploaded_thumbnail(params[:collection][:thumbnail_upload]) if params[:collection][:thumbnail_upload]
end

# Deletes any previous thumbnails. The thumbnail indexer (see services/hyrax/indexes_thumbnails)
# checks if an uploaded thumbnail exists in the public folder before indexing the thumbnail path.
def delete_uploaded_thumbnail
Expand Down Expand Up @@ -99,6 +115,13 @@ def files

private

def configure_show_sort_fields
kirkkwang marked this conversation as resolved.
Show resolved Hide resolved
# In the CollectionsControllerDecorator, we clear the sort fields and add our own to have
# the ability to sort the index with custom fields. However, this also affects the show page.
# Here we set the sort fields back to the defaults for the show page.
blacklight_config.sort_fields = CatalogController.blacklight_config.sort_fields
end

# branding specific methods
def process_banner_input
return update_existing_banner if params["banner_unchanged"] == "true"
Expand Down
18 changes: 18 additions & 0 deletions app/forms/hyrax/forms/pcdm_collection_form_decorator.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,25 @@
# frozen_string_literal: true
# OVERRIDE Hyraxv5.0.0 to add the ability to upload a collection thumbnail

Hyrax::Forms::PcdmCollectionForm.class_eval do
include Hyrax::FormFields(:basic_metadata)
include Hyrax::FormFields(:bulkrax_metadata)
include CollectionAccessFiltering

ThumbnailInfoPrepopulator = lambda do |_options = nil|
kirkkwang marked this conversation as resolved.
Show resolved Hide resolved
self.thumbnail_info ||= begin
thumbnail_info = CollectionBrandingInfo.where(collection_id: id.to_s, role: "thumbnail").first
if thumbnail_info
thumbnail_file = File.split(thumbnail_info.local_path).last
alttext = thumbnail_info.alt_text
file_location = thumbnail_info.local_path
relative_path = "/" + thumbnail_info.local_path.split("/")[-4..-1].join("/")
{ file: thumbnail_file, full_path: file_location, relative_path:, alttext: }
else
{} # Always return at least an empty hash
end
end
end

property :thumbnail_info, virtual: true, prepopulator: ThumbnailInfoPrepopulator
end
3 changes: 2 additions & 1 deletion app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ def group_navigation_presenter
@group_navigation_presenter ||= Hyku::Admin::Group::NavigationPresenter.new(params:)
end

def collection_thumbnail(_document, _image_options = {}, _url_options = {})
def collection_thumbnail(document, _image_options = {}, _url_options = {})
return image_tag(document['thumbnail_path_ss']) if document['thumbnail_path_ss'].present?
return super if Site.instance.default_collection_image.blank?

image_tag(Site.instance.default_collection_image&.url)
Expand Down
10 changes: 10 additions & 0 deletions app/presenters/hyrax/collection_presenter_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,16 @@ def banner_file
end
end

def thumbnail_record
kirkkwang marked this conversation as resolved.
Show resolved Hide resolved
CollectionBrandingInfo.where(collection_id: id, role: "thumbnail")
.select(:local_path, :alt_text, :target_url).map do |thumbnail|
{ alttext: thumbnail.alt_text,
file: File.split(thumbnail.local_path).last,
file_location: "/#{thumbnail.local_path.split('/')[-4..-1].join('/')}",
linkurl: thumbnail.target_url }
end
end

# Begin Featured Collections Methods
def collection_featurable?
user_can_feature_collection? && solr_document.public?
Expand Down
9 changes: 9 additions & 0 deletions app/services/hyrax/thumbnail_path_service_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@

module Hyrax
module ThumbnailPathServiceDecorator
def call(object)
return super unless object.try(:collection?)

collection_thumbnail = CollectionBrandingInfo.where(collection_id: object.id.to_s, role: "thumbnail").first
return collection_thumbnail.local_path.gsub(Rails.public_path.to_s, '') if collection_thumbnail

default_image
end

def default_image
Site.instance.default_work_image&.url || super
end
Expand Down
77 changes: 77 additions & 0 deletions app/views/hyrax/dashboard/collections/_form_branding.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -163,4 +163,81 @@
</div> <!-- end col-12 -->
</div> <!-- end row branding-logo-list -->
</div> <!-- end fileuploadlogo -->

<label><strong><%= t('.thumbnail.label') %></strong></label>
<p><%= t('.thumbnail.description') %></p>

<div id="fileuploadthumbnail">
<!-- Redirect browsers with JavaScript disabled to the origin page -->
<noscript><input type="hidden" name="redirect" value="<%= main_app.root_path %>" /></noscript>
<!-- The table listing the files available for upload/download -->

<!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
<div class="row fileupload-buttonbar">
<div class="col-4">
<!-- The fileinput-button span is used to style the file input field as button -->
<span class="btn btn-success fileinput-button">
<span class="fa fa-plus"></span>
<span><%= t('.choose_file') %></span>
<input type="file" name="files[]" single />
</span>
</div> <!-- end col-4 -->

<!-- The global progress state -->
<div class="col-8 fileupload-progress branding-thumbnail-progress fade">
<!-- The global progress bar -->
<div class="progress" role="progressbar" aria-valuemin="0" aria-valuemax="100">
<div class="progress-bar progress-bar-striped progress-bar-animated bg-success" style="width:0%;"></div>
</div>
<!-- The extended global progress state -->
<div class="progress-extended">&nbsp;</div>
</div> <!-- end col-8 fileupload-progress fade -->
</div> <!-- end row fileupload-buttonbar -->

<div class="row branding-thumbnail-list">
<div class="col-12">
<div class="container">
<%# Where the request to display the branding comes from. %>
<% if f.object.thumbnail_info[:file] %>
<div id="thumbnail">
<div class="row branding-thumbnail-row">
<div class="col-sm-3">
<span class="name">
<i><%= image_tag(f.object.thumbnail_info[:relative_path],
height: "36",
alt: f.object.thumbnail_info[:alttext].presence || f.object.thumbnail_info[:file]) %></i>
<span><%= f.object.thumbnail_info[:file] %></span>
<input type="hidden" name="thumbnail_unchanged" value="true" />
</span>
</div>
<div class="col-sm-4 branding-thumbnail-input">
<label for="thumbnail_text"><%= t('.alt_text') %>
<input id="thumbnail_text" class="branding-thumbnail-input" type="text" name="thumbnail_text[]" value="<%= f.object.thumbnail_info[:alttext] %>" />
</label>
</div>

<div class="col-sm-2">
<button class="btn btn-danger delete branding-thumbnail-remove" data-type="DELETE" data-url="/" onclick=$("#thumbnail").remove();>
<span class="fa fa-times"></span>
<span class="controls-remove-text"><%= t('.remove') %></span>
<span class="sr-only">
<%= t('.previous') %>
<span class="controls-field-name-text"><%= t('.remove_current_thumbnail') %></span>
</span>
</button>
</div> <!-- end col-sm-2 -->
</div> <!-- row branding-thumbnail-row -->
</div> <!-- end thumbnail -->
<div role="presentation" class="table table-striped"><span class="files"></span></div>
<% else %>
<div role="presentation" class="table table-striped"><span class="files"></span></div>
<% end %>

<!-- The global file processing state -->
<span class="fileupload-process"></span>
</div> <!-- end container -->
</div> <!-- end row branding-thumbnail-list -->
</div> <!-- end row branding-thumbnail-list -->
</div> <!-- fileuploadthumbnail -->

</div> <!-- end set-access-controls -->
2 changes: 1 addition & 1 deletion app/views/hyrax/my/collections/_list_collections.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<span class="<%= Hyrax::ModelIcon.css_class_for(::Collection) %> collection-icon-small"></span>
<% else %>
<%# OVERRIDE begin %>
<%= image_tag(collection_presenter.thumbnail_path, alt: block_for(name: 'default_collection_image_text') || "#{collection_presenter.title_or_label} #{t('hyrax.dashboard.my.sr.thumbnail')}") %>
<%= image_tag(collection_presenter.thumbnail_path, alt: collection_presenter.thumbnail_record.first[:alttext] || block_for(name: 'default_collection_image_text') || "#{collection_presenter.title_or_label} #{t('hyrax.dashboard.my.sr.thumbnail')}") %>
<%# OVERRIDE end %>
<% end %>
</div>
Expand Down
37 changes: 37 additions & 0 deletions app/views/hyrax/uploads/_js_templates_branding.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,40 @@
</span>
{% } %}
</script>

<!-- The template to display thumbnail in the table once upload is complete -->
<script id="thumbnail-template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<span class="template-download fade show">
<div id="thumbnail">
<div class="row branding-thumbnail-row">
<div class="col-sm-3">
<span class="name">
<span>{%=file.name%}</span>
<input type="hidden" name="thumbnail_files[]" value="{%=file.id%}">
</span>
{% if (file.error) { %}
<span><span class="badge badge-danger"><%= t('.error') %></span> {%=file.error%}</span>
{% } %}
</div>

<div class="col-sm-4 branding-thumbnail-input">
<label for="thumbnail_text"><%= t('.alt_text') %></label>
<input id="thumbnail_text" type="text" name="thumbnail_text[]" class="form-control branding-thumbnail-input" single>
</div>

<div class="col-sm-2">
<button class="btn btn-link remove branding-thumbnail-remove" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}" onclick=$("#thumbnail").remove(); {% if (file.deleteWithCredentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}>
<span class="fa fa-times"></span>
<span class="controls-remove-text"><%= t('.remove') %></span>
<span class="sr-only">
<%= t('.previous') %>
<span class="controls-field-name-text"><%= t('.remove_new_thumbnail') %></span>
</span>
</button>
</div> <!-- end col-sm-2 -->
</div> <!-- row branding-thumbnail-row -->
</div> <!-- end container thumbnail -->
</span>
{% } $("div#thumbnail").remove(); %}
</script>
20 changes: 18 additions & 2 deletions config/initializers/hyrax.rb
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,22 @@
# Temporary path to hold uploads before they are ingested into FCrepo.
# This must be a lambda that returns a Pathname
config.upload_path = lambda {
if Site.account&.s3_bucket
if Site.account&.s3_bucket.present?
# For S3, no need to create directories
"uploads/#{Apartment::Tenant.current}"
else
ENV['HYRAX_UPLOAD_PATH'].present? ? Pathname.new(File.join(ENV['HYRAX_UPLOAD_PATH'], Apartment::Tenant.current)) : Rails.public_path.join('uploads', Apartment::Tenant.current)
# Determine the base upload path
base_path = if ENV['HYRAX_UPLOAD_PATH'].present?
Pathname.new(File.join(ENV['HYRAX_UPLOAD_PATH'], Apartment::Tenant.current))
else
Rails.root.join('uploads', Apartment::Tenant.current)
end

# Create the directory if it doesn't exist
FileUtils.mkdir_p(base_path) unless Dir.exist?(base_path)

# Return the path
base_path
end
}

Expand Down Expand Up @@ -242,3 +254,7 @@

Hyrax::MemberPresenterFactory.file_presenter_class = Hyrax::IiifAv::IiifFileSetPresenter
Hyrax::PcdmMemberPresenterFactory.file_presenter_class = Hyrax::IiifAv::IiifFileSetPresenter

Hyrax::Transactions::Container.namespace('collection_resource') do |ops|
ops.register 'save_collection_thumbnail', Hyrax::Transactions::Steps::SaveCollectionThumbnail.new
end
25 changes: 25 additions & 0 deletions lib/hyrax/transactions/collection_update_decorator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

# Require the necessary file at the beginning
require 'hyrax/transactions/transaction'

# OVERRIDE Hyrax v5.0.0 to add the ability to upload a collection thumbnail
module Hyrax
module Transactions
# Use class_eval to reopen the class for modification
CollectionUpdate.class_eval do
# Override the initialize method to alter the default steps
def initialize(container: Container, steps: nil)
# Define the new steps array including the new thumbnail step
new_steps = ['change_set.apply',
'collection_resource.save_collection_banner',
'collection_resource.save_collection_logo',
'collection_resource.save_collection_thumbnail', # Your new step
kirkkwang marked this conversation as resolved.
Show resolved Hide resolved
'collection_resource.save_acl'].freeze

# Use the new steps array if steps argument is nil, else use provided steps
super(container:, steps: steps || new_steps)
end
end
end
end
Loading
Loading