';
+ html +='
';
html +='';
html +='
';
html +='
' + truncateLongString(asset.name, <%= Constants::FILENAME_TRUNCATION_LENGTH %>);
diff --git a/app/assets/stylesheets/steps.scss b/app/assets/stylesheets/steps.scss
index 96e40789e..17806d96b 100644
--- a/app/assets/stylesheets/steps.scss
+++ b/app/assets/stylesheets/steps.scss
@@ -143,25 +143,6 @@
background-color: rgba(95, 95, 95, .1);
}
- .attachment-thumbnail {
- display: inline-block;
- height: 160px;
- margin: 16px 10px 5px;
- overflow: hidden;
- text-align: center;
-
- img {
- border-radius: 5px;
- max-height: 100%;
- max-width: 100%;
- }
-
- i.fas {
- font-size: 100px;
- line-height: 160px;
- }
- }
-
.no-shadow {
box-shadow: none;
}
diff --git a/app/assets/stylesheets/themes/scinote.scss b/app/assets/stylesheets/themes/scinote.scss
index 1d9157b2c..c9e5a14c0 100644
--- a/app/assets/stylesheets/themes/scinote.scss
+++ b/app/assets/stylesheets/themes/scinote.scss
@@ -1442,6 +1442,32 @@ table.dataTable {
}
}
+.attachment-thumbnail {
+ display: inline-block;
+ height: 160px;
+ margin: 16px 10px 5px;
+ overflow: hidden;
+ text-align: center;
+ width: 100%;
+
+ img {
+ border-radius: 5px;
+ max-height: 100%;
+ max-width: 100%;
+ }
+
+ .fas {
+ font-size: 100px;
+ line-height: 160px;
+ }
+
+ &:not(.new) {
+ background-image: url("/images/medium/processing.gif");
+ background-position: center;
+ background-repeat: no-repeat;
+ }
+}
+
// Image preview modal
.modal-file-preview {
background: transparent;
@@ -1484,6 +1510,9 @@ table.dataTable {
.file-preview-container {
align-items: center;
+ background-image: url("/images/medium/processing.gif");
+ background-position: center;
+ background-repeat: no-repeat;
color: $gray-dark;
display: -moz-flex;
display: -webkit-flex;
diff --git a/app/models/asset.rb b/app/models/asset.rb
index de5202ea8..7c1faca30 100644
--- a/app/models/asset.rb
+++ b/app/models/asset.rb
@@ -1,9 +1,12 @@
+# frozen_string_literal: true
+
class Asset < ApplicationRecord
include ActiveStorage::Downloading
include SearchableModel
include DatabaseHelper
include Encryptor
include WopiUtil
+ include ActiveStorageFileUtil
require 'tempfile'
# Lock duration set to 30 minutes
@@ -191,27 +194,25 @@ class Asset < ApplicationRecord
def previewable?
return false unless file.attached?
- previewable_document? || previewable_image?
+ previewable_document?(blob) || previewable_image?
end
def medium_preview
return file.variant(resize: Constants::MEDIUM_PIC_FORMAT) if previewable_image?
- '/images/medium/processing.gif'
- # file.preview(resize: Constants::MEDIUM_PIC_FORMAT)
+ file.preview(resize: Constants::MEDIUM_PIC_FORMAT)
end
def large_preview
return file.variant(resize: Constants::LARGE_PIC_FORMAT) if previewable_image?
- '/images/large/processing.gif'
- # file.preview(resize: Constants::LARGE_PIC_FORMAT)
+ file.preview(resize: Constants::LARGE_PIC_FORMAT)
end
def file_name
return '' unless file.attached?
- file.blob&.filename&.to_s
+ file.blob&.filename&.sanitized
end
def file_size
@@ -221,11 +222,9 @@ class Asset < ApplicationRecord
end
def content_type
- file&.blob&.content_type
- end
+ return '' unless file.attached?
- def file_size
- file&.blob&.byte_size
+ file&.blob&.content_type
end
def duplicate
@@ -455,25 +454,6 @@ class Asset < ApplicationRecord
Rails.root.join('tmp')
end
- def previewable_document?
- previewable = Constants::PREVIEWABLE_FILE_TYPES.include?(file.content_type)
-
- filename = file.filename.to_s
- content_type = file.content_type
-
- extensions = %w(.xlsx .docx .pptx .xls .doc .ppt)
- # Mimetype sometimes recognizes Office files as zip files
- # In this case we also check the extension of the given file
- # Otherwise the conversion should fail if the file is being something else
- previewable ||= (content_type == 'application/zip' && extensions.include?(File.extname(filename)))
-
- # Mimetype also sometimes recognizes '.xls' and '.ppt' files as
- # application/x-ole-storage (https://github.com/minad/mimemagic/issues/50)
- previewable ||= (content_type == 'application/x-ole-storage' && %w(.xls .ppt).include?(File.extname(filename)))
-
- previewable
- end
-
def previewable_image?
file.blob&.content_type =~ %r{^image/#{Regexp.union(Constants::WHITELISTED_IMAGE_TYPES)}}
end
diff --git a/app/models/tiny_mce_asset.rb b/app/models/tiny_mce_asset.rb
index 6f56d307a..4178192b7 100644
--- a/app/models/tiny_mce_asset.rb
+++ b/app/models/tiny_mce_asset.rb
@@ -73,7 +73,7 @@ class TinyMceAsset < ApplicationRecord
def file_name
return '' unless image.attached?
- image.blob&.filename&.to_s
+ image.blob&.filename&.sanitized
end
def file_size
@@ -83,11 +83,9 @@ class TinyMceAsset < ApplicationRecord
end
def content_type
- image&.blob&.content_type
- end
+ return '' unless image.attached?
- def file_size
- image&.blob&.byte_size
+ image&.blob&.content_type
end
def preview
@@ -140,7 +138,7 @@ class TinyMceAsset < ApplicationRecord
if exists?
order(:id).each do |tiny_mce_asset|
asset_guid = get_guid(tiny_mce_asset.id)
- asset_file_name = "rte-#{asset_guid.to_s + File.extname(tiny_mce_asset.image.filename.to_s)}"
+ asset_file_name = "rte-#{asset_guid.to_s + tiny_mce_asset.image.blob.filename.extension}"
ostream.put_next_entry("#{dir}/#{asset_file_name}")
ostream.print(tiny_mce_asset.image.download)
input_file.close
@@ -172,7 +170,7 @@ class TinyMceAsset < ApplicationRecord
tiny_img_clone.transaction do
tiny_img_clone.save!
- tiny_img_clone.image.attach(io: image.download, filename: image.filename.to_s)
+ tiny_img_clone.image.attach(io: image.download, filename: image.filename.sanitized)
end
return false unless tiny_img_clone.persisted?
diff --git a/app/services/active_storage/previewer/libreoffice_previewer.rb b/app/services/active_storage/previewer/libreoffice_previewer.rb
new file mode 100644
index 000000000..23c18b5ce
--- /dev/null
+++ b/app/services/active_storage/previewer/libreoffice_previewer.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module ActiveStorage
+ class Previewer
+ class LibreofficePreviewer < Previewer
+ class << self
+ include ActiveStorageFileUtil
+
+ def accept?(blob)
+ previewable_document?(blob)
+ end
+ end
+
+ def preview
+ download_blob_to_tempfile do |input|
+ work_dir = File.dirname(input.path)
+ basename = File.basename(input.path, '.*')
+ preview_file = File.join(work_dir, "#{basename}.png")
+
+ Rails.logger.info "Starting preparing document preview for file #{blob.filename.sanitized}..."
+
+ begin
+ success = system(
+ "#{libreoffice_path} --headless --invisible --convert-to png --outdir #{work_dir} #{input.path}"
+ )
+
+ unless success && File.file?(preview_file)
+ raise StandardError, "There was an error generating document preview, blob id: #{blob.id}"
+ end
+
+ yield io: File.open(preview_file), filename: "#{blob.filename.base}.png", content_type: 'image/png'
+
+ Rails.logger.info "Finished preparing document preview for file #{blob.filename.sanitized}."
+ ensure
+ File.delete(preview_file) if File.file?(preview_file)
+ end
+ end
+ end
+
+ private
+
+ def tempdir
+ Rails.root.join('tmp')
+ end
+
+ def libreoffice_path
+ ENV['LIBREOFFICE_PATH'] || 'libreoffice'
+ end
+ end
+ end
+end
diff --git a/lib/active_storage/service/custom_s3_service.rb b/app/services/active_storage/service/custom_s3_service.rb
similarity index 100%
rename from lib/active_storage/service/custom_s3_service.rb
rename to app/services/active_storage/service/custom_s3_service.rb
diff --git a/app/utilities/active_storage_file_util.rb b/app/utilities/active_storage_file_util.rb
new file mode 100644
index 000000000..1bdf89a75
--- /dev/null
+++ b/app/utilities/active_storage_file_util.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module ActiveStorageFileUtil
+ # Method expects instance of ActiveStorage::Blob as argument
+ def previewable_document?(blob)
+ previewable = Constants::PREVIEWABLE_FILE_TYPES.include?(blob.content_type)
+
+ file_extension = blob.filename.extension
+ content_type = blob.content_type
+
+ extensions = %w(.xlsx .docx .pptx .xls .doc .ppt)
+ # Mimetype sometimes recognizes Office files as zip files
+ # In this case we also check the extension of the given file
+ # Otherwise the conversion should fail if the file is being something else
+ previewable ||= (content_type == 'application/zip' && extensions.include?(file_extension))
+
+ # Mimetype also sometimes recognizes '.xls' and '.ppt' files as
+ # application/x-ole-storage (https://github.com/minad/mimemagic/issues/50)
+ previewable ||= (content_type == 'application/x-ole-storage' && %w(.xls .ppt).include?(file_extension))
+
+ previewable
+ end
+end
diff --git a/app/views/shared/_asset_link.html.erb b/app/views/shared/_asset_link.html.erb
index fb762f4c5..e63960561 100644
--- a/app/views/shared/_asset_link.html.erb
+++ b/app/views/shared/_asset_link.html.erb
@@ -1,15 +1,9 @@
<%= link_to download_asset_path(asset),
class: 'file-preview-link',
id: "modal_link#{asset.id}",
- data: { no_turbolink: true, id: true, status: 'asset-present', 'preview-url': asset_file_preview_path(asset) } do %>
- <% if display_image_tag && asset.previewable? %>
- <%= image_tag asset.medium_preview %>
-
- <%= truncate(asset.file_name, length: Constants::FILENAME_TRUNCATION_LENGTH) %>
-
- <% else %>
-
- <%= truncate(asset.file_name, length: Constants::FILENAME_TRUNCATION_LENGTH) %>
-
- <% end %>
+ data: { no_turbolink: true,
+ id: true,
+ status: 'asset-present',
+ 'preview-url': asset_file_preview_path(asset) } do %>
+ <%= render partial: 'shared/asset_placeholder.html.erb', locals: { edit_page: false, asset: asset } %>
<% end %>
diff --git a/app/views/steps/attachments/_placeholder.html.erb b/app/views/shared/_asset_placeholder.html.erb
similarity index 86%
rename from app/views/steps/attachments/_placeholder.html.erb
rename to app/views/shared/_asset_placeholder.html.erb
index 56c7acf81..e8426337d 100644
--- a/app/views/steps/attachments/_placeholder.html.erb
+++ b/app/views/shared/_asset_placeholder.html.erb
@@ -10,7 +10,7 @@
<%= truncate(asset.file_name, length: Constants::FILENAME_TRUNCATION_LENGTH) %>
- <%= t('protocols.steps.attachments.modified_label') %> <%= l(asset.updated_at, format: :full_date) if asset.updated_at %>
+ <%= t('assets.placeholder.modified_label') %> <%= l(asset.updated_at, format: :full_date) if asset.updated_at %>
<%= number_to_human_size(asset.file_size) %>
diff --git a/app/views/steps/_empty_step.html.erb b/app/views/steps/_empty_step.html.erb
index d68b3edeb..4a890c65a 100644
--- a/app/views/steps/_empty_step.html.erb
+++ b/app/views/steps/_empty_step.html.erb
@@ -69,7 +69,7 @@
diff --git a/config/application.rb b/config/application.rb
index fc530cda8..bf21c82a1 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -9,7 +9,7 @@ Bundler.require(*Rails.groups)
module Scinote
class Application < Rails::Application
# Initialize configuration defaults for originally generated Rails version.
- config.load_defaults 5.1
+ config.load_defaults 5.2
# Settings in config/environments/* take precedence over those specified here.
# Application configuration should go into files in config/initializers
diff --git a/config/initializers/active_storage.rb b/config/initializers/active_storage.rb
new file mode 100644
index 000000000..8833691a2
--- /dev/null
+++ b/config/initializers/active_storage.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+Rails.application.config.active_storage.previewers = [ActiveStorage::Previewer::PopplerPDFPreviewer,
+ ActiveStorage::Previewer::LibreofficePreviewer]
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 14407e7b5..2116ac1e7 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -1763,7 +1763,6 @@ en:
sort_old: "Oldest first ↑"
sort_atoz: "Name ↓"
sort_ztoa: "Name ↑"
- modified_label: "Modified:"
new:
add_step_title: "Add new step"
tab_checklists: "Checklists"
@@ -1900,6 +1899,8 @@ en:
add_image: 'Add'
file_name: 'File name'
file_name_placeholder: 'Image'
+ placeholder:
+ modified_label: "Modified:"
wopi_supported_text_formats_title: 'Only .docx, .docm, .odt file formats are supported for editing in Word Online.'
wopi_supported_table_formats_title: 'Only .xlsx, .xlsm, .xlsb, .ods file formats are supported for editing in Excel Online.'
wopi_supported_presentation_formats_title: 'Only .pptx, ppsx, .odp file formats are supported for editing in Powerpoint Online.'